Initial public release of Warp.

Repo-Sync-Origin: warpdotdev/warp-internal@12af1d983b
This commit is contained in:
David Stern
2026-04-28 08:43:33 -05:00
commit 0dbd3d567a
4982 changed files with 1431549 additions and 0 deletions
+192
View File
@@ -0,0 +1,192 @@
use super::auth::AuthClient;
use super::ServerApi;
use crate::ai::generate_block_title::api::{GenerateBlockTitleRequest, GenerateBlockTitleResponse};
use crate::server::{
block::{Block, DisplaySetting},
graphql::{get_request_context, get_user_facing_error_message},
};
use anyhow::anyhow;
use async_trait::async_trait;
use chrono::Utc;
use cynic::{MutationBuilder, QueryBuilder};
#[cfg(test)]
use mockall::automock;
use std::convert::TryFrom;
use warp_core::channel::{Channel, ChannelState};
use warp_graphql::{
mutations::{
share_block::{BlockInput, ShareBlock, ShareBlockResult, ShareBlockVariables},
unshare_block::{
UnshareBlock, UnshareBlockInput, UnshareBlockResult, UnshareBlockVariables,
},
},
queries::get_blocks_for_user::{
Block as GqlBlock, GetBlocksForUser, GetBlocksForUserVariables,
},
};
#[cfg_attr(test, automock)]
#[cfg_attr(not(target_family = "wasm"), async_trait)]
#[cfg_attr(target_family = "wasm", async_trait(?Send))]
pub trait BlockClient: 'static + Send + Sync {
/// Unshares a block identified at `block_id`.
async fn unshare_block(&self, block_id: String) -> Result<(), anyhow::Error>;
/// Uploads a given block to the server via the /share_block endpoint.
async fn save_block(
&self,
block: &Block,
title: Option<String>,
show_prompt: bool,
display_setting: DisplaySetting,
) -> Result<String, anyhow::Error>;
async fn blocks_owned_by_user(&self) -> Result<Vec<Block>, anyhow::Error>;
async fn generate_shared_block_title(
&self,
request: GenerateBlockTitleRequest,
) -> Result<GenerateBlockTitleResponse, anyhow::Error>;
}
#[cfg_attr(not(target_family = "wasm"), async_trait)]
#[cfg_attr(target_family = "wasm", async_trait(?Send))]
impl BlockClient for ServerApi {
async fn unshare_block(&self, block_uid: String) -> Result<(), anyhow::Error> {
let variables = UnshareBlockVariables {
input: UnshareBlockInput { block_uid },
request_context: get_request_context(),
};
let operation = UnshareBlock::build(variables);
let response = self.send_graphql_request(operation, None).await?;
match response.unshare_block {
UnshareBlockResult::UnshareBlockOutput(output) => {
if output.success {
Ok(())
} else {
Err(anyhow!("Failed to unshare block"))
}
}
UnshareBlockResult::UserFacingError(error) => {
Err(anyhow!(get_user_facing_error_message(error)))
}
UnshareBlockResult::Unknown => Err(anyhow!("Failed to unshare block")),
}
}
async fn save_block(
&self,
block: &Block,
title: Option<String>,
show_prompt: bool,
display_setting: DisplaySetting,
) -> Result<String, anyhow::Error> {
let variables = ShareBlockVariables {
block: BlockInput {
command: block.command.as_deref(),
embed_display_setting: display_setting.into(),
output: block.output.as_deref(),
show_prompt,
stylized_command: block.stylized_command.as_deref(),
stylized_output: block.stylized_output.as_deref(),
stylized_prompt: block.stylized_prompt.as_deref(),
stylized_prompt_and_command: block.stylized_prompt_and_command.as_deref(),
time_started_term: Some(block.time_started_term.with_timezone(&Utc).into()),
title: title.as_deref(),
},
request_context: get_request_context(),
};
let operation = ShareBlock::build(variables);
let response = self.send_graphql_request(operation, None).await?;
match response.share_block {
ShareBlockResult::ShareBlockOutput(output) => {
let mut created_url =
format!("{}{}", ChannelState::server_root_url(), output.url_ending);
// If this is a preview build, ensure the link routes to a preview build.
if matches!(ChannelState::channel(), Channel::Preview) {
created_url.push_str("?preview=true");
}
Ok(created_url)
}
ShareBlockResult::UserFacingError(error) => {
Err(anyhow!(get_user_facing_error_message(error)))
}
ShareBlockResult::Unknown => Err(anyhow!("Failed to share block")),
}
}
async fn blocks_owned_by_user(&self) -> Result<Vec<Block>, anyhow::Error> {
let variables = GetBlocksForUserVariables {
request_context: get_request_context(),
};
let operation = GetBlocksForUser::build(variables);
let response = self.send_graphql_request(operation, None).await?;
match response.user {
warp_graphql::queries::get_blocks_for_user::UserResult::UserOutput(user_output) => {
Ok(user_output
.user
.blocks
.into_iter()
.filter_map(|block| block.try_into().ok())
.collect())
}
warp_graphql::queries::get_blocks_for_user::UserResult::Unknown => {
Err(anyhow!("Unable to fetch blocks"))
}
}
}
async fn generate_shared_block_title(
&self,
request: GenerateBlockTitleRequest,
) -> Result<GenerateBlockTitleResponse, anyhow::Error> {
let auth_token = self.get_or_refresh_access_token().await?;
let request_builder = self.client.post(format!(
"{}/ai/generate_block_title",
ChannelState::server_root_url()
));
let response = if let Some(token) = auth_token.as_bearer_token() {
request_builder.bearer_auth(token)
} else {
request_builder
}
.json(&request)
.send()
.await?
.error_for_status()?
.json()
.await?;
Ok(response)
}
}
impl TryFrom<GqlBlock> for Block {
type Error = anyhow::Error;
fn try_from(value: GqlBlock) -> Result<Self, Self::Error> {
match (value.uid, value.time_started_term) {
(uid, Some(time_started_term)) => {
Ok(Block {
id: Some(uid.into_inner()),
command: value.command,
output: None,
stylized_command: None,
stylized_output: None,
pwd: None,
time_started_term: time_started_term.utc().into(),
// This is a dummy value - we are no longer using time_completed_term,
// and GqlBlock does not have a time_completed_term field.
time_completed_term: time_started_term.utc().into(),
stylized_prompt: None,
stylized_prompt_and_command: None,
})
}
_ => Err(anyhow!("missing id or time_started_term")),
}
}
}