tea_context/providers/
session.rs1use std::str::FromStr;
2
3use tea_protocol::RecordId;
4
5use crate::{
6 BudgetBehavior, CacheScope, ConflictClaim, ConflictKey, ConflictMode, ContextError,
7 ContextErrorCode, ContextProvider, ContextProviderFuture, ContextProviderId, ContextRequest,
8 PromptAuthority, PromptModule, PromptModuleId, PromptPriority, PromptProvenance, PromptSegment,
9 PromptSegmentId, TrustLevel,
10};
11
12#[derive(Debug, Clone)]
14pub struct SessionSummaryProvider {
15 id: ContextProviderId,
16 summary: Option<(String, RecordId, TrustLevel)>,
17}
18
19impl SessionSummaryProvider {
20 pub fn empty() -> Result<Self, ContextError> {
26 Ok(Self {
27 id: ContextProviderId::from_str("builtin.session_summary").map_err(value_error)?,
28 summary: None,
29 })
30 }
31
32 pub fn new(
38 summary: impl Into<String>,
39 record_id: RecordId,
40 trust: TrustLevel,
41 ) -> Result<Self, ContextError> {
42 let summary = summary.into();
43 let id = ContextProviderId::from_str("builtin.session_summary").map_err(value_error)?;
44 validate(&id, &summary, record_id, trust)?;
45 Ok(Self {
46 id,
47 summary: Some((summary, record_id, trust)),
48 })
49 }
50}
51
52impl ContextProvider for SessionSummaryProvider {
53 fn id(&self) -> &ContextProviderId {
54 &self.id
55 }
56
57 fn provide(&self, _request: ContextRequest) -> ContextProviderFuture<'_> {
58 let id = self.id.clone();
59 let summary = self.summary.clone();
60 Box::pin(async move {
61 let Some((summary, record_id, trust)) = summary else {
62 return Ok(Vec::new());
63 };
64 let segment = PromptSegment::new(
65 PromptSegmentId::from_str("session.summary").map_err(value_error)?,
66 summary,
67 PromptProvenance::new(id, "session_record", Some(record_id.to_string()))
68 .map_err(value_error)?,
69 trust,
70 CacheScope::Session,
71 BudgetBehavior::Omit,
72 )
73 .map_err(value_error)?
74 .with_conflict(ConflictClaim::new(
75 ConflictKey::from_str("session.summary").map_err(value_error)?,
76 ConflictMode::Replaceable,
77 ));
78 Ok(vec![
79 PromptModule::new(
80 PromptModuleId::from_str("session.summary").map_err(value_error)?,
81 PromptAuthority::Session,
82 PromptPriority::new(0),
83 vec![segment],
84 )
85 .map_err(value_error)?,
86 ])
87 })
88 }
89}
90
91fn validate(
92 id: &ContextProviderId,
93 summary: &str,
94 record_id: RecordId,
95 trust: TrustLevel,
96) -> Result<(), ContextError> {
97 PromptSegment::new(
98 PromptSegmentId::from_str("session.summary").map_err(value_error)?,
99 summary,
100 PromptProvenance::new(id.clone(), "session_record", Some(record_id.to_string()))
101 .map_err(value_error)?,
102 trust,
103 CacheScope::Session,
104 BudgetBehavior::Omit,
105 )
106 .map(|_| ())
107 .map_err(value_error)
108}
109
110fn value_error(error: impl std::fmt::Display) -> ContextError {
111 ContextError::new(ContextErrorCode::InvalidValue, error.to_string())
112}