1use std::sync::Arc;
2
3use crate::schema::json_schema_for;
4use anyhow::{Result, anyhow};
5use assistant_tool::{ActionLog, Tool, ToolResult};
6use chrono::{Local, Utc};
7use gpui::{AnyWindowHandle, App, Entity, Task};
8use language_model::{LanguageModel, LanguageModelRequest, LanguageModelToolSchemaFormat};
9use project::Project;
10use schemars::JsonSchema;
11use serde::{Deserialize, Serialize};
12use ui::IconName;
13
14#[derive(Debug, Serialize, Deserialize, JsonSchema)]
15#[serde(rename_all = "snake_case")]
16pub enum Timezone {
17 /// Use UTC for the datetime.
18 Utc,
19 /// Use local time for the datetime.
20 Local,
21}
22
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 Tool for NowTool {
32 fn name(&self) -> String {
33 "now".into()
34 }
35
36 fn needs_confirmation(&self, _: &serde_json::Value, _: &Entity<Project>, _: &App) -> bool {
37 false
38 }
39
40 fn may_perform_edits(&self) -> bool {
41 false
42 }
43
44 fn description(&self) -> String {
45 "Returns the current datetime in RFC 3339 format. Only use this tool when the user specifically asks for it or the current task would benefit from knowing the current datetime.".into()
46 }
47
48 fn icon(&self) -> IconName {
49 IconName::Info
50 }
51
52 fn input_schema(&self, format: LanguageModelToolSchemaFormat) -> Result<serde_json::Value> {
53 json_schema_for::<NowToolInput>(format)
54 }
55
56 fn ui_text(&self, _input: &serde_json::Value) -> String {
57 "Get current time".to_string()
58 }
59
60 fn run(
61 self: Arc<Self>,
62 input: serde_json::Value,
63 _request: Arc<LanguageModelRequest>,
64 _project: Entity<Project>,
65 _action_log: Entity<ActionLog>,
66 _model: Arc<dyn LanguageModel>,
67 _window: Option<AnyWindowHandle>,
68 _cx: &mut App,
69 ) -> ToolResult {
70 let input: NowToolInput = match serde_json::from_value(input) {
71 Ok(input) => input,
72 Err(err) => return Task::ready(Err(anyhow!(err))).into(),
73 };
74
75 let now = match input.timezone {
76 Timezone::Utc => Utc::now().to_rfc3339(),
77 Timezone::Local => Local::now().to_rfc3339(),
78 };
79 let text = format!("The current datetime is {now}.");
80
81 Task::ready(Ok(text.into())).into()
82 }
83}