syncable_cli/agent/tools/platform/
current_context.rs1use rig::completion::ToolDefinition;
6use rig::tool::Tool;
7use serde::{Deserialize, Serialize};
8use serde_json::json;
9
10use crate::agent::tools::error::{ErrorCategory, format_error_for_llm};
11use crate::platform::PlatformSession;
12
13#[derive(Debug, Deserialize)]
15pub struct CurrentContextArgs {}
16
17#[derive(Debug, thiserror::Error)]
19#[error("Current context error: {0}")]
20pub struct CurrentContextError(String);
21
22#[derive(Debug, Clone, Serialize, Deserialize, Default)]
27pub struct CurrentContextTool;
28
29impl CurrentContextTool {
30 pub fn new() -> Self {
32 Self
33 }
34}
35
36impl Tool for CurrentContextTool {
37 const NAME: &'static str = "current_context";
38
39 type Error = CurrentContextError;
40 type Args = CurrentContextArgs;
41 type Output = String;
42
43 async fn definition(&self, _prompt: String) -> ToolDefinition {
44 ToolDefinition {
45 name: Self::NAME.to_string(),
46 description: r#"Get the currently selected project context.
47
48Returns information about the currently selected project and organization,
49or indicates if no project is selected.
50
51**Use Cases:**
52- Checking which project is currently active before operations
53- Verifying context after selection
54- Determining if context setup is needed
55
56**No Prerequisites:**
57- This tool can be called at any time
58- Returns helpful message if no project is selected"#
59 .to_string(),
60 parameters: json!({
61 "type": "object",
62 "properties": {},
63 "required": []
64 }),
65 }
66 }
67
68 async fn call(&self, _args: Self::Args) -> Result<Self::Output, Self::Error> {
69 let session = match PlatformSession::load() {
71 Ok(s) => s,
72 Err(e) => {
73 return Ok(format_error_for_llm(
74 "current_context",
75 ErrorCategory::InternalError,
76 &format!("Failed to load platform session: {}", e),
77 Some(vec![
78 "The session file may be corrupted",
79 "Try selecting a project with select_project",
80 ]),
81 ));
82 }
83 };
84
85 if !session.is_project_selected() {
87 let result = json!({
88 "success": true,
89 "has_context": false,
90 "message": "No project currently selected",
91 "suggestion": "Use list_organizations and list_projects to find a project, then select_project to set context"
92 });
93
94 return serde_json::to_string_pretty(&result)
95 .map_err(|e| CurrentContextError(format!("Failed to serialize: {}", e)));
96 }
97
98 let result = json!({
100 "success": true,
101 "has_context": true,
102 "context": {
103 "project_id": session.project_id,
104 "project_name": session.project_name,
105 "organization_id": session.org_id,
106 "organization_name": session.org_name,
107 "display": session.display_context(),
108 "last_updated": session.last_updated.map(|dt| dt.to_rfc3339())
109 }
110 });
111
112 serde_json::to_string_pretty(&result)
113 .map_err(|e| CurrentContextError(format!("Failed to serialize: {}", e)))
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120
121 #[test]
122 fn test_tool_name() {
123 assert_eq!(CurrentContextTool::NAME, "current_context");
124 }
125
126 #[test]
127 fn test_tool_creation() {
128 let tool = CurrentContextTool::new();
129 assert!(format!("{:?}", tool).contains("CurrentContextTool"));
130 }
131}