pub struct Client { /* private fields */ }Expand description
Async gateway client. Share it behind an Arc; methods take &self.
Every call is POST {gateway_url}/api/<method> with the session’s bearer token and
headers, after re-checking the URL against the Policy. A client created with a
Cursor access token (Client::connect_cursor / Client::with_cursor_token)
re-runs EnsureSandBox once and retries when the gateway answers 401 or 417; persist
the new session from Client::take_refreshed_session.
use grokbot_api::{Client, ClientOptions, Session};
let client = Client::new(
Session::new("https://box.us1.cursorvm.com", "gateway-token"),
ClientOptions::default(),
)?;
for agent in client.list_agents().await? {
println!("{} {}", agent.id, agent.display_name());
}Implementations§
Source§impl Client
impl Client
Sourcepub async fn begin_attachment_upload(
&self,
agent_id: &str,
session_id: Option<&str>,
file_name: &str,
size_bytes: u64,
sha256_hex: Option<&str>,
) -> Result<BeginUpload>
pub async fn begin_attachment_upload( &self, agent_id: &str, session_id: Option<&str>, file_name: &str, size_bytes: u64, sha256_hex: Option<&str>, ) -> Result<BeginUpload>
BeginGrokBotAttachmentUpload. session_id defaults to the agent’s viewer session.
Sourcepub async fn presign_attachment_upload_parts(
&self,
upload_token: &str,
parts: &[(u32, [u8; 32])],
) -> Result<PresignedParts>
pub async fn presign_attachment_upload_parts( &self, upload_token: &str, parts: &[(u32, [u8; 32])], ) -> Result<PresignedParts>
PresignGrokBotAttachmentUploadParts: parts are (part_number, sha256). With no
parts it re-presigns the single PUT.
Sourcepub async fn complete_attachment_upload(
&self,
upload_token: &str,
) -> Result<CompletedUpload>
pub async fn complete_attachment_upload( &self, upload_token: &str, ) -> Result<CompletedUpload>
CompleteGrokBotAttachmentUpload.
Sourcepub async fn abort_attachment_upload(&self, upload_token: &str) -> Result<()>
pub async fn abort_attachment_upload(&self, upload_token: &str) -> Result<()>
AbortGrokBotAttachmentUpload (best effort cleanup).
Sourcepub async fn resolve_attachment_reads(
&self,
agent_id: &str,
session_id: Option<&str>,
paths: &[String],
) -> Result<Vec<AttachmentRead>>
pub async fn resolve_attachment_reads( &self, agent_id: &str, session_id: Option<&str>, paths: &[String], ) -> Result<Vec<AttachmentRead>>
ResolveGrokBotAttachmentReads: presigned GETs for attachment paths/aliases.
Sourcepub async fn upload_attachment(
&self,
agent_id: &str,
session_id: Option<&str>,
file_name: &str,
data: &[u8],
progress: impl FnMut(UploadProgress) + Send,
) -> Result<UploadedAttachment>
pub async fn upload_attachment( &self, agent_id: &str, session_id: Option<&str>, file_name: &str, data: &[u8], progress: impl FnMut(UploadProgress) + Send, ) -> Result<UploadedAttachment>
Upload data as file_name for agent_id and return the alias.
Handles SINGLE_PUT and MULTIPART, calls progress as bytes are acknowledged,
and aborts the upload on any failure after Begin. Refusals, USE_BOX and a missing
Cursor session come back as Error::Attachment.
Source§impl Client
impl Client
Sourcepub fn new(session: Session, opts: ClientOptions) -> Result<Self>
pub fn new(session: Session, opts: ClientOptions) -> Result<Self>
Client for an existing gateway session. The URL is checked against the policy on every call.
Sourcepub fn with_cursor_token(
session: Session,
cursor_token: impl Into<String>,
opts: ClientOptions,
) -> Result<Self>
pub fn with_cursor_token( session: Session, cursor_token: impl Into<String>, opts: ClientOptions, ) -> Result<Self>
Like Client::new, but keeps the Cursor access token so a 401 triggers one
EnsureSandBox re-exchange and a retry.
Sourcepub async fn connect_cursor(
access_token: &str,
opts: ClientOptions,
) -> Result<Self>
pub async fn connect_cursor( access_token: &str, opts: ClientOptions, ) -> Result<Self>
EnsureSandBox then build a client that can re-exchange.
Sourcepub fn take_refreshed_session(&self) -> Option<Session>
pub fn take_refreshed_session(&self) -> Option<Session>
The new session if a 401 re-exchange happened since the last call (persist it).
Sourcepub async fn call_raw(&self, method: &str, body: Value) -> Result<Value>
pub async fn call_raw(&self, method: &str, body: Value) -> Result<Value>
Call any gateway method with a raw JSON body and return the raw JSON response. Handles the 401/417 re-exchange like the typed methods.
Sourcepub async fn list_agents(&self) -> Result<Vec<Agent>>
pub async fn list_agents(&self) -> Result<Vec<Agent>>
listAgents {} → bots and groups (hidden ones included; check hidden_from_sidebar).
Sourcepub async fn create_agent(&self, input: &CreateAgent) -> Result<Option<Agent>>
pub async fn create_agent(&self, input: &CreateAgent) -> Result<Option<Agent>>
createAgent {name, description, title, avatarShape, avatarColor, origin: "user"}.
Sourcepub async fn update_agent(
&self,
id: &str,
profile: &AgentProfile,
) -> Result<Value>
pub async fn update_agent( &self, id: &str, profile: &AgentProfile, ) -> Result<Value>
updateAgent {id, profile: {name, description, title?, avatarShape?, avatarColor?}}.
Sourcepub async fn delete_agent(&self, id: &str) -> Result<Value>
pub async fn delete_agent(&self, id: &str) -> Result<Value>
deleteAgent {id}.
Sourcepub async fn set_agent_notify_on_updates(
&self,
id: &str,
enabled: bool,
) -> Result<Value>
pub async fn set_agent_notify_on_updates( &self, id: &str, enabled: bool, ) -> Result<Value>
setAgentNotifyOnUpdates {id, isEnabled}.
setAgentHiddenFromSidebar {id, isHidden}.
Sourcepub async fn create_group(&self, input: &CreateGroup) -> Result<Option<Agent>>
pub async fn create_group(&self, input: &CreateGroup) -> Result<Option<Agent>>
createGroup {name, description, memberAgentIds} (1..=6 distinct members, no nested groups).
Sourcepub async fn set_group_members(
&self,
group_id: &str,
member_agent_ids: &[String],
) -> Result<Option<Agent>>
pub async fn set_group_members( &self, group_id: &str, member_agent_ids: &[String], ) -> Result<Option<Agent>>
setGroupMembers {id, memberAgentIds}.
Sourcepub fn set_agent_session(&self, agent_id: &str, session_id: &str)
pub fn set_agent_session(&self, agent_id: &str, session_id: &str)
Route calls for agent_id through session_id (a shared agent’s viewer session),
sent as sessionId on sendPrompt, promptAcceptanceStatus and
getAgentTranscriptTail. Client::list_team_agents sets this automatically.
Sourcepub fn has_cursor_session(&self) -> bool
pub fn has_cursor_session(&self) -> bool
Whether this client holds a Cursor access token (needed for attachments and team agents).
Sourcepub async fn list_team_agents(&self) -> Result<Option<Vec<TeamAgent>>>
pub async fn list_team_agents(&self) -> Result<Option<Vec<TeamAgent>>>
Cursor backend GrokBotService/ListGrokBotTeamAgents: your agents plus team agents
shared with you. Ok(None) when this client has no Cursor access token (a plain
gateway session). Shared agents’ viewer sessions are remembered for later calls.
Sourcepub async fn send_prompt(&self, req: &SendPrompt) -> Result<SendReceipt>
pub async fn send_prompt(&self, req: &SendPrompt) -> Result<SendReceipt>
sendPrompt {agentId, prompt, clientNonce, replyToId?, attachmentPaths?, attachmentNames?, sessionId?} → receipt only.
Replies arrive later: poll Client::transcript_tail. On error use
Error::delivery: Unknown means the prompt may have landed, so check the
transcript or Client::prompt_acceptance_status before resending. A gateway
refusal ({status: "refused"} / {accepted: false}) is returned as
Error::Http with status 422.
Sourcepub async fn prompt_acceptance_status(
&self,
agent_id: &str,
client_nonce: &str,
) -> Result<AcceptanceStatus>
pub async fn prompt_acceptance_status( &self, agent_id: &str, client_nonce: &str, ) -> Result<AcceptanceStatus>
promptAcceptanceStatus {agentId, clientNonce}: the gateway’s own lookup of
whether a prompt with this nonce landed (what the desktop app uses when a send’s
outcome is uncertain).
Sourcepub async fn transcript_tail(
&self,
id: &str,
limit: u32,
before_seq: Option<u64>,
) -> Result<Transcript>
pub async fn transcript_tail( &self, id: &str, limit: u32, before_seq: Option<u64>, ) -> Result<Transcript>
getAgentTranscriptTail {id, limit, beforeSeq?} (limit clamped to 1..=200).
Omitting before_seq returns the newest page. When the response includes
nextBeforeSeq, pass it here to walk older pages (as the desktop app does).
Sourcepub async fn transcript_history(
&self,
id: &str,
page_size: u32,
max_entries: usize,
) -> Result<Transcript>
pub async fn transcript_history( &self, id: &str, page_size: u32, max_entries: usize, ) -> Result<Transcript>
Walk getAgentTranscriptTail pages until the chat is exhausted or max_entries
is reached. Newest page first; returned entries are oldest → newest.
Sourcepub async fn thread(&self, id: &str, root_id: &str) -> Result<Transcript>
pub async fn thread(&self, id: &str, root_id: &str) -> Result<Transcript>
getAgentThread {id, rootId}.
Sourcepub async fn get_agent_workflows(&self, id: &str) -> Result<Vec<Workflow>>
pub async fn get_agent_workflows(&self, id: &str) -> Result<Vec<Workflow>>
getAgentWorkflows {id}. The library is shared per box; id is any bot id.
Sourcepub async fn import_agent_workflow_text(
&self,
id: &str,
markdown: &str,
) -> Result<ImportResult>
pub async fn import_agent_workflow_text( &self, id: &str, markdown: &str, ) -> Result<ImportResult>
importAgentWorkflowText {id, markdown}.
Sourcepub async fn delete_agent_workflow(
&self,
id: &str,
workflow_id: &str,
) -> Result<Value>
pub async fn delete_agent_workflow( &self, id: &str, workflow_id: &str, ) -> Result<Value>
deleteAgentWorkflow {id, workflowId}.
Sourcepub async fn resolve_local_tool_permission(
&self,
agent_id: &str,
entry_id: &str,
request_id: &str,
resolution: LocalToolResolution,
) -> Result<Value>
pub async fn resolve_local_tool_permission( &self, agent_id: &str, entry_id: &str, request_id: &str, resolution: LocalToolResolution, ) -> Result<Value>
resolveLocalToolPermission {agentId, entryId, requestId, resolution: "allow-once"|"deny"}.
Only call on an explicit user decision.
Sourcepub async fn resolve_auto_review_approval(
&self,
agent_id: &str,
entry_id: &str,
request_id: &str,
resolution: AutoReviewResolution,
) -> Result<Value>
pub async fn resolve_auto_review_approval( &self, agent_id: &str, entry_id: &str, request_id: &str, resolution: AutoReviewResolution, ) -> Result<Value>
resolveAutoReviewApproval {agentId, entryId, requestId, resolution: "approved"|"denied"}.
Only call on an explicit user decision.