1use std::sync::Arc;
2
3use agent_client_protocol as acp;
4use chrono::{Local, Utc};
5use gpui::{App, SharedString, Task};
6use schemars::JsonSchema;
7use serde::{Deserialize, Serialize};
8
9use crate::{AgentTool, ToolCallEventStream, ToolInput};
10
11#[derive(Debug, Serialize, Deserialize, JsonSchema)]
12#[serde(rename_all = "snake_case")]
13#[schemars(inline)]
14pub enum Timezone {
15 /// Use UTC for the datetime.
16 Utc,
17 /// Use local time for the datetime.
18 Local,
19}
20
21/// Returns the current datetime in RFC 3339 format.
22/// Only use this tool when the user specifically asks for it or the current task would benefit from knowing the current datetime.
23#[derive(Debug, Serialize, Deserialize, JsonSchema)]
24pub struct NowToolInput {
25 /// The timezone to use for the datetime.
26 timezone: Timezone,
27}
28
29pub struct NowTool;
30
31impl AgentTool for NowTool {
32 type Input = NowToolInput;
33 type Output = String;
34
35 const NAME: &'static str = "now";
36
37 fn kind() -> acp::ToolKind {
38 acp::ToolKind::Other
39 }
40
41 fn initial_title(
42 &self,
43 _input: Result<Self::Input, serde_json::Value>,
44 _cx: &mut App,
45 ) -> SharedString {
46 "Get current time".into()
47 }
48
49 fn run(
50 self: Arc<Self>,
51 input: ToolInput<Self::Input>,
52 _event_stream: ToolCallEventStream,
53 cx: &mut App,
54 ) -> Task<Result<String, String>> {
55 cx.spawn(async move |_cx| {
56 let input = input
57 .recv()
58 .await
59 .map_err(|e| format!("Failed to receive tool input: {e}"))?;
60 let now = match input.timezone {
61 Timezone::Utc => Utc::now().to_rfc3339(),
62 Timezone::Local => Local::now().to_rfc3339(),
63 };
64 Ok(format!("The current datetime is {now}."))
65 })
66 }
67}