ag_agent/agent/
instruction.rs1use crate::channel::AgentRequestKind;
4
5pub fn normalize_instruction_conversation_id(
8 provider_conversation_id: Option<&str>,
9) -> Option<String> {
10 provider_conversation_id
11 .map(str::trim)
12 .filter(|value| !value.is_empty())
13 .map(ToString::to_string)
14}
15
16#[derive(Debug, Clone, Copy, Eq, PartialEq)]
18pub enum InstructionDeliveryMode {
19 BootstrapFull,
21 DeltaOnly,
24 BootstrapWithReplay,
27}
28
29pub fn plan_app_server_instruction_delivery(
32 request_kind: &AgentRequestKind,
33 current_provider_conversation_id: Option<&str>,
34 persisted_instruction_conversation_id: Option<&str>,
35 should_replay_transcript: bool,
36) -> InstructionDeliveryMode {
37 if should_replay_transcript {
38 return InstructionDeliveryMode::BootstrapWithReplay;
39 }
40
41 if matches!(
42 request_kind,
43 AgentRequestKind::UtilityPrompt | AgentRequestKind::AccountRead
44 ) {
45 return InstructionDeliveryMode::BootstrapFull;
46 }
47
48 if normalize_instruction_conversation_id(current_provider_conversation_id).as_deref()
49 == persisted_instruction_conversation_id
50 {
51 return InstructionDeliveryMode::DeltaOnly;
52 }
53
54 InstructionDeliveryMode::BootstrapFull
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60
61 #[test]
62 fn test_plan_app_server_instruction_delivery_uses_delta_only_for_matching_state() {
65 let persisted_instruction_conversation_id =
67 normalize_instruction_conversation_id(Some("thread-123"));
68
69 let mode = plan_app_server_instruction_delivery(
71 &AgentRequestKind::SessionResume,
72 Some("thread-123"),
73 persisted_instruction_conversation_id.as_deref(),
74 false,
75 );
76
77 assert_eq!(mode, InstructionDeliveryMode::DeltaOnly);
79 }
80
81 #[test]
82 fn test_plan_app_server_instruction_delivery_uses_bootstrap_with_replay_after_reset() {
85 let persisted_instruction_conversation_id =
87 normalize_instruction_conversation_id(Some("thread-123"));
88
89 let mode = plan_app_server_instruction_delivery(
91 &AgentRequestKind::SessionResume,
92 Some("thread-456"),
93 persisted_instruction_conversation_id.as_deref(),
94 true,
95 );
96
97 assert_eq!(mode, InstructionDeliveryMode::BootstrapWithReplay);
99 }
100
101 #[test]
102 fn test_plan_app_server_instruction_delivery_bootstraps_full_for_new_context() {
104 let persisted_instruction_conversation_id =
106 normalize_instruction_conversation_id(Some("thread-123"));
107
108 let mode = plan_app_server_instruction_delivery(
110 &AgentRequestKind::SessionResume,
111 Some("thread-456"),
112 persisted_instruction_conversation_id.as_deref(),
113 false,
114 );
115
116 assert_eq!(mode, InstructionDeliveryMode::BootstrapFull);
118 }
119
120 #[test]
121 fn test_plan_app_server_instruction_delivery_bootstraps_full_for_utility_prompt() {
124 let persisted_instruction_conversation_id =
126 normalize_instruction_conversation_id(Some("thread-123"));
127
128 let mode = plan_app_server_instruction_delivery(
130 &AgentRequestKind::UtilityPrompt,
131 Some("thread-123"),
132 persisted_instruction_conversation_id.as_deref(),
133 false,
134 );
135
136 assert_eq!(mode, InstructionDeliveryMode::BootstrapFull);
138 }
139}