agent_sdk_core/application/
projection.rs1use crate::{
8 context::{ContextItem, ContextProjection, ProjectionRole},
9 domain::{AgentError, AgentErrorKind, RetryClassification},
10 provider::{
11 ProviderMessage, ProviderMessageRole, ProviderProjectedMetadata, ProviderProjectionPolicy,
12 ProviderRequest,
13 },
14};
15
16pub fn project_context_projection(
20 projection: &ContextProjection,
21 policy: &ProviderProjectionPolicy,
22) -> Result<ProviderRequest, AgentError> {
23 if projection.items.is_empty() {
24 return Err(AgentError::new(
25 AgentErrorKind::ProjectionFailure,
26 RetryClassification::RepairNeeded,
27 "provider projection requires at least one admitted context item",
28 ));
29 }
30
31 Ok(ProviderRequest {
32 schema_version: ProviderRequest::SCHEMA_VERSION,
33 projection_policy_ref: policy.projection_policy_ref.clone(),
34 projection_item_count: projection.items.len(),
35 structured_output_hint: None,
36 messages: projection
37 .items
38 .iter()
39 .map(|item| project_item(item, policy))
40 .collect(),
41 })
42}
43
44fn project_item(item: &ContextItem, policy: &ProviderProjectionPolicy) -> ProviderMessage {
45 ProviderMessage {
46 role: role_for_item(item),
47 content: projected_content(item),
48 privacy: item.privacy_class,
49 projected_metadata: policy
50 .allow_private_metadata_projection
51 .then(|| projected_metadata(item)),
52 }
53}
54
55fn projected_content(item: &ContextItem) -> String {
56 item.inline_redacted_summary
57 .clone()
58 .unwrap_or_else(|| item.redacted_summary.clone())
59}
60
61fn role_for_item(item: &ContextItem) -> ProviderMessageRole {
62 match item.projection_role {
63 ProjectionRole::System => ProviderMessageRole::System,
64 ProjectionRole::Developer => ProviderMessageRole::Developer,
65 ProjectionRole::User => ProviderMessageRole::User,
66 ProjectionRole::ToolResult => ProviderMessageRole::Tool,
67 _ => ProviderMessageRole::Context,
68 }
69}
70
71fn projected_metadata(item: &ContextItem) -> ProviderProjectedMetadata {
72 ProviderProjectedMetadata {
73 source_kind: item.source_ref.kind.clone(),
74 source_id: item.source_ref.as_str().to_string(),
75 destination_kind: item.destination_ref.kind.clone(),
76 destination_id: item.destination_ref.as_str().to_string(),
77 subject_kind: format!("{:?}", item.producer_ref.kind),
78 subject_id: item.producer_ref.as_str().to_string(),
79 }
80}