Skip to main content

starweaver_context/
runtime_state.rs

1//! Ephemeral state used only while an agent context is executing.
2
3use std::collections::BTreeMap;
4
5use serde::{Deserialize, Serialize};
6use starweaver_core::Metadata;
7
8use crate::{
9    AgentStreamQueueRegistry, ContextLifecycleState, ToolCapabilityGrant, ToolIdWrapper,
10    WrapperMetadata,
11};
12
13/// Runtime-only context state excluded from resumable session snapshots.
14///
15/// This component is flattened into [`crate::AgentContext`] serialization to preserve the
16/// pre-decomposition JSON shape. Durable restoration continues to use
17/// [`crate::ResumableState`], which deliberately does not include these fields.
18#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
19pub struct RuntimeEphemeralState {
20    /// Force environment/runtime context injection on the next filter pass.
21    #[serde(default)]
22    pub force_inject_context: bool,
23    /// Context-injection tag names that should be stripped or refreshed.
24    #[serde(default, skip_serializing_if = "Vec::is_empty")]
25    pub injected_context_tags: Vec<String>,
26    /// Active context management tool names.
27    #[serde(default, skip_serializing_if = "Vec::is_empty")]
28    pub context_manage_tool_names: Vec<String>,
29    /// Active tool capability tags.
30    #[serde(default, skip_serializing_if = "Vec::is_empty")]
31    pub tool_tags: Vec<String>,
32    /// Tool call ID wrapper for provider-normalized tool IDs.
33    #[serde(default, skip_serializing_if = "ToolIdWrapper::is_empty")]
34    pub tool_id_wrapper: ToolIdWrapper,
35    /// Runtime stream queue registry placeholder.
36    #[serde(default, skip_serializing_if = "AgentStreamQueueRegistry::is_empty")]
37    pub agent_stream_queues: AgentStreamQueueRegistry,
38    /// Wrapper metadata carried by the running context.
39    #[serde(default, skip_serializing_if = "Metadata::is_empty")]
40    pub wrapper_metadata: WrapperMetadata,
41    /// Runtime lifecycle state.
42    #[serde(default, skip_serializing_if = "ContextLifecycleState::is_default")]
43    pub lifecycle: ContextLifecycleState,
44    /// Whether run-scoped toolsets have completed their exit lifecycle.
45    #[serde(skip, default = "default_run_toolsets_closed")]
46    pub run_toolsets_closed: bool,
47    /// Current runtime run step for context-aware preparation.
48    #[serde(skip)]
49    pub current_run_step: usize,
50    /// Host-authorized per-tool grants, never persisted in resumable state.
51    #[serde(skip)]
52    pub tool_capability_grants: BTreeMap<String, ToolCapabilityGrant>,
53}
54
55impl Default for RuntimeEphemeralState {
56    fn default() -> Self {
57        Self {
58            force_inject_context: false,
59            injected_context_tags: default_injected_context_tags(),
60            context_manage_tool_names: Vec::new(),
61            tool_tags: Vec::new(),
62            tool_id_wrapper: ToolIdWrapper::default(),
63            agent_stream_queues: AgentStreamQueueRegistry::default(),
64            wrapper_metadata: Metadata::default(),
65            lifecycle: ContextLifecycleState::default(),
66            run_toolsets_closed: true,
67            current_run_step: 0,
68            tool_capability_grants: BTreeMap::new(),
69        }
70    }
71}
72
73const fn default_run_toolsets_closed() -> bool {
74    true
75}
76
77fn default_injected_context_tags() -> Vec<String> {
78    vec![
79        "runtime-context".to_string(),
80        "environment-context".to_string(),
81    ]
82}