Skip to main content

lash_core/runtime/process/
wake.rs

1use std::time::SystemTime;
2
3use crate::plugin::PluginError;
4
5use super::events::{ProcessWake, ProcessWakeDelivery};
6use super::model::{ProcessId, ProcessScope};
7use super::time::epoch_ms_from_system_time;
8
9/// Extracts the model-facing wake input from a process wake event payload.
10pub fn process_wake_input_from_event_payload(payload: &serde_json::Value) -> String {
11    payload
12        .pointer("/text")
13        .or_else(|| payload.pointer("/value"))
14        .map(wake_payload_value_to_string)
15        .unwrap_or_else(|| payload.to_string())
16}
17
18/// Renders a durable process wake as model-visible chronological context.
19pub fn process_wake_turn_text(wake: &ProcessWakeDelivery) -> String {
20    format!(
21        "Background process wake\nProcess: {}\nEvent: {} #{}\nWake input:\n{}",
22        wake.process_id, wake.event_type, wake.sequence, wake.input
23    )
24}
25
26pub fn process_wake_turn_cause(wake: &ProcessWakeDelivery) -> crate::TurnCause {
27    crate::TurnCause {
28        id: wake.wake_id.clone(),
29        event_type: wake.event_type.clone(),
30        origin: crate::MessageOrigin::Process {
31            process_id: wake.process_id.clone(),
32            event_type: wake.event_type.clone(),
33            sequence: wake.sequence,
34            wake_id: Some(wake.wake_id.clone()),
35            caused_by: wake.process_caused_by.clone(),
36        },
37        text: process_wake_turn_text(wake),
38    }
39}
40
41#[derive(Clone, Debug)]
42pub struct ProcessWakeDeliveryRequest {
43    pub target_scope: ProcessScope,
44    pub process_id: ProcessId,
45    pub sequence: u64,
46    pub event_type: String,
47    pub event_invocation: crate::RuntimeInvocation,
48    pub process_caused_by: Option<crate::CausalRef>,
49    pub wake: ProcessWake,
50    pub occurred_at: SystemTime,
51}
52
53pub fn process_wake_delivery(
54    request: ProcessWakeDeliveryRequest,
55) -> Result<ProcessWakeDelivery, PluginError> {
56    let ProcessWakeDeliveryRequest {
57        target_scope,
58        process_id,
59        sequence,
60        event_type,
61        event_invocation,
62        process_caused_by,
63        wake,
64        occurred_at,
65    } = request;
66    let target_scope_id = target_scope.id();
67    let wake_id = crate::stable_hash::stable_json_sha256_hex(&(
68        target_scope_id.as_str(),
69        wake.dedupe_key.as_str(),
70    ))
71    .map_err(|err| {
72        PluginError::Session(format!(
73            "failed to hash wake delivery for process `{process_id}`: {err}"
74        ))
75    })?;
76    Ok(ProcessWakeDelivery {
77        wake_id: format!("wake:{wake_id}"),
78        target_session_id: target_scope.session_id,
79        target_scope_id,
80        process_id,
81        sequence,
82        event_type,
83        event_invocation,
84        process_caused_by,
85        dedupe_key: wake.dedupe_key,
86        input: wake.input,
87        created_at_ms: epoch_ms_from_system_time(occurred_at),
88    })
89}
90
91fn wake_payload_value_to_string(value: &serde_json::Value) -> String {
92    value
93        .as_str()
94        .map(ToOwned::to_owned)
95        .unwrap_or_else(|| value.to_string())
96}