use std::time::Duration;
use serde_json::{Value, json};
use crate::client::{Client, grokbot_service_call};
use crate::error::Result;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum BoxIntent {
AppForeground,
AppBackground,
ChatOpen,
ComposerFocus,
Typing,
UploadStart,
FileOpen,
ComputerOpen,
}
impl BoxIntent {
pub fn proto_name(self) -> &'static str {
match self {
Self::AppForeground => "GROK_BOT_BOX_INTENT_APP_FOREGROUND",
Self::AppBackground => "GROK_BOT_BOX_INTENT_APP_BACKGROUND",
Self::ChatOpen => "GROK_BOT_BOX_INTENT_CHAT_OPEN",
Self::ComposerFocus => "GROK_BOT_BOX_INTENT_COMPOSER_FOCUS",
Self::Typing => "GROK_BOT_BOX_INTENT_TYPING",
Self::UploadStart => "GROK_BOT_BOX_INTENT_UPLOAD_START",
Self::FileOpen => "GROK_BOT_BOX_INTENT_FILE_OPEN",
Self::ComputerOpen => "GROK_BOT_BOX_INTENT_COMPUTER_OPEN",
}
}
}
fn ms(v: Option<&Value>) -> Duration {
let n = match v {
Some(Value::Number(n)) => n.as_u64(),
Some(Value::String(s)) => s.parse().ok(),
_ => None,
};
Duration::from_millis(n.unwrap_or(0))
}
impl Client {
pub async fn report_desktop_activity(
&self,
install_id: &str,
active: bool,
) -> Result<Duration> {
let tok = self.cursor_token_opt().ok_or(crate::Error::Attachment(
crate::UploadFailure::NoCursorSession,
))?;
let v = grokbot_service_call(
&tok,
"ReportGrokBotDesktopActivity",
&json!({"installId": install_id, "active": active}),
self.options(),
)
.await?;
Ok(ms(v.get("leaseMs")))
}
pub async fn report_client_presence(
&self,
agent_id: &str,
viewing: bool,
typing: bool,
intent: Option<BoxIntent>,
) -> Result<Duration> {
let tok = self.cursor_token_opt().ok_or(crate::Error::Attachment(
crate::UploadFailure::NoCursorSession,
))?;
let mut body = json!({"agentId": agent_id, "viewing": viewing, "surface": "desktop"});
if typing {
body["trigger"] = json!(1); }
if let Some(i) = intent {
body["intent"] = json!(i as u8 + 1);
}
let v = grokbot_service_call(&tok, "ReportGrokBotClientPresence", &body, self.options())
.await?;
Ok(ms(v.get("presenceTtlMs")))
}
}