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
+101
View File
@@ -0,0 +1,101 @@
//! Tools for loading a [`ChannelConfig`] from the external config generator binary.
//!
//! For non-bundled builds, the generator is invoked at runtime. For bundled builds, the config
//! is embedded at compile time via the build script.
use warp_core::channel::ChannelConfig;
/// The name of the config generator binary, expected to be on PATH.
const CONFIG_BIN_NAME: &str = "warp-channel-config";
#[macro_export]
#[cfg(windows)]
macro_rules! path_concat {
($path:expr, $file:expr) => {
concat!($path, "\\", $file)
};
}
#[macro_export]
#[cfg(not(windows))]
macro_rules! path_concat {
($path:expr, $file:expr) => {
concat!($path, "/", $file)
};
}
#[macro_export]
macro_rules! load_config {
($channel:expr) => {{
#[cfg(feature = "release_bundle")]
{
channel_config::load_config_from_embedded(include_str!($crate::path_concat!(
env!("OUT_DIR"),
concat!($channel, "_config.json")
)))
}
#[cfg(not(feature = "release_bundle"))]
{
channel_config::load_config_from_generator($channel)
}
}};
}
pub use load_config;
/// Invokes the config generator binary at runtime and deserializes its JSON output into a
/// [`ChannelConfig`].
#[cfg_attr(feature = "release_bundle", expect(dead_code))]
pub fn load_config_from_generator(channel: &str) -> ChannelConfig {
let target_family = if cfg!(target_family = "wasm") {
"wasm"
} else {
"native"
};
let target_os = if cfg!(target_os = "macos") {
"macos"
} else if cfg!(target_os = "windows") {
"windows"
} else {
"linux"
};
let output = command::blocking::Command::new(CONFIG_BIN_NAME)
.arg("--channel")
.arg(channel)
.arg("--target-family")
.arg(target_family)
.arg("--target-os")
.arg(target_os)
.output()
.unwrap_or_else(|err| {
if err.kind() == std::io::ErrorKind::NotFound {
panic!(
"\n\n'{CONFIG_BIN_NAME}' was not found on PATH.\n\n\
To build internal channels, run:\n\
\n\
\x20 ./script/install_channel_config\n\n"
)
}
panic!("Failed to execute '{CONFIG_BIN_NAME}': {err}")
});
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
panic!("Config generator failed for channel '{channel}':\n{stderr}");
}
serde_json::from_slice(&output.stdout).unwrap_or_else(|err| {
let stdout = String::from_utf8_lossy(&output.stdout);
panic!("Failed to parse config generator output for channel '{channel}': {err}\nOutput:\n{stdout}")
})
}
/// Deserializes a [`ChannelConfig`] from a JSON string embedded at compile time.
///
/// This is used to load the channel configuration in release bundles, where configuration
/// is embedded at compile time instead of being generated at runtime.
#[cfg_attr(not(feature = "release_bundle"), expect(dead_code))]
pub fn load_config_from_embedded(json: &str) -> ChannelConfig {
serde_json::from_str(json)
.unwrap_or_else(|err| panic!("Failed to parse embedded channel config: {err}"))
}
+24
View File
@@ -0,0 +1,24 @@
// On Windows, we don't want to display a console window when the application is running in release
// builds. See https://doc.rust-lang.org/reference/runtime.html#the-windows_subsystem-attribute.
#![cfg_attr(feature = "release_bundle", windows_subsystem = "windows")]
#[path = "channel_config.rs"]
mod channel_config;
use anyhow::Result;
use warp_core::{
channel::{Channel, ChannelState},
features,
};
// Simple wrapper around warp::run() for dev channel builds.
fn main() -> Result<()> {
ChannelState::set(
ChannelState::new(Channel::Dev, channel_config::load_config!("dev"))
.with_additional_features(features::DEBUG_FLAGS)
.with_additional_features(features::DOGFOOD_FLAGS)
.with_additional_features(features::PREVIEW_FLAGS),
);
warp::run()
}
+266
View File
@@ -0,0 +1,266 @@
//! Generates a JSON Schema file describing Warp's user-facing settings.
//!
//! Usage:
//! ```
//! cargo run --bin generate_settings_schema -- [--channel dev|preview|stable] [output_path]
//! ```
use std::collections::HashSet;
use std::io::Write;
use schemars::SchemaGenerator;
use serde_json::{Map, Value};
use settings::schema::SettingSchemaEntry;
use warp_core::features::{FeatureFlag, DEBUG_FLAGS, DOGFOOD_FLAGS, PREVIEW_FLAGS, RELEASE_FLAGS};
/// Ensures all `inventory::submit!` registrations from the app crate's
/// dependency tree are linked into the binary.
///
/// Binary targets only link crate code that is transitively referenced.
/// Without an explicit reference to the `warp` library, the linker will
/// not include most of the app's object files and the `inventory`
/// submissions they contain.
fn ensure_settings_linked() {
let _ = std::hint::black_box(warp::settings::RESTORE_SESSION);
}
/// Recursively strips `minimum`, `maximum`, and `format` from integer and
/// number schemas. schemars derives these from Rust type bounds (e.g. `u8`
/// → `minimum: 0, maximum: 255, format: "uint8"`), which are misleading
/// for settings whose valid domain is narrower than the type allows.
fn strip_numeric_metadata(value: &mut Value) {
match value {
Value::Object(map) => {
let is_numeric = map
.get("type")
.and_then(Value::as_str)
.is_some_and(|t| t == "integer" || t == "number");
if is_numeric {
map.remove("minimum");
map.remove("maximum");
map.remove("format");
}
for val in map.values_mut() {
strip_numeric_metadata(val);
}
}
Value::Array(arr) => {
for val in arr {
strip_numeric_metadata(val);
}
}
_ => {}
}
}
/// Removes `{"enum": [], "type": "string"}` entries from `oneOf` arrays.
/// schemars emits an empty enum bucket for externally-tagged enums when all
/// unit variants have individual descriptions (and are therefore promoted to
/// separate `oneOf` branches with `const`). The empty bucket is unreachable
/// and confuses schema consumers.
fn strip_empty_enum_entries(value: &mut Value) {
match value {
Value::Object(map) => {
if let Some(Value::Array(one_of)) = map.get_mut("oneOf") {
one_of.retain(|entry| {
!matches!(entry, Value::Object(obj)
if obj.get("enum").is_some_and(|e| e.as_array().is_some_and(|a| a.is_empty()))
)
});
}
for val in map.values_mut() {
strip_empty_enum_entries(val);
}
}
Value::Array(arr) => {
for val in arr {
strip_empty_enum_entries(val);
}
}
_ => {}
}
}
fn active_flags_for_channel(channel: &str) -> HashSet<FeatureFlag> {
let mut flags = HashSet::new();
let flag_lists: &[&[FeatureFlag]] = match channel {
"stable" => &[RELEASE_FLAGS],
"preview" => &[RELEASE_FLAGS, PREVIEW_FLAGS],
"dev" => &[RELEASE_FLAGS, PREVIEW_FLAGS, DOGFOOD_FLAGS, DEBUG_FLAGS],
other => {
eprintln!("Unknown channel '{other}', defaulting to dev");
&[RELEASE_FLAGS, PREVIEW_FLAGS, DOGFOOD_FLAGS, DEBUG_FLAGS]
}
};
for list in flag_lists {
for flag in *list {
flags.insert(*flag);
}
}
flags
}
/// Creates intermediate hierarchy objects so that a setting at e.g.
/// `appearance.text` is nested under `properties.appearance.properties.text.properties`.
fn ensure_hierarchy<'a>(
root_properties: &'a mut Map<String, Value>,
hierarchy: &str,
) -> &'a mut Map<String, Value> {
let segments: Vec<&str> = hierarchy.split('.').collect();
let mut current = root_properties;
for segment in segments {
// Ensure the segment object exists
let entry = current.entry(segment.to_string()).or_insert_with(|| {
Value::Object({
let mut m = Map::new();
m.insert("type".to_string(), Value::String("object".to_string()));
m.insert("properties".to_string(), Value::Object(Map::new()));
m
})
});
// Navigate into its properties
current = entry
.as_object_mut()
.expect("hierarchy node should be an object")
.entry("properties")
.or_insert_with(|| Value::Object(Map::new()))
.as_object_mut()
.expect("properties should be an object");
}
current
}
fn main() {
ensure_settings_linked();
let args: Vec<String> = std::env::args().collect();
let mut channel = "dev";
let mut output_path: Option<&str> = None;
let mut i = 1;
while i < args.len() {
match args[i].as_str() {
"--channel" => {
i += 1;
if i < args.len() {
channel = &args[i];
}
}
arg if !arg.starts_with('-') => {
output_path = Some(arg);
}
other => {
eprintln!("Unknown argument: {other}");
std::process::exit(1);
}
}
i += 1;
}
let active_flags = active_flags_for_channel(channel);
let mut generator = SchemaGenerator::default();
let mut root_properties = Map::new();
let mut entry_count = 0;
for entry in inventory::iter::<SettingSchemaEntry> {
// Skip private settings
if entry.is_private {
continue;
}
// Skip settings whose feature flag is not active
if let Some(flag) = entry.feature_flag {
if !active_flags.contains(&flag) {
continue;
}
}
let type_schema = (entry.schema_fn)(&mut generator);
let mut schema_value: Value = type_schema.to_value();
// Compute default value — prefer file default over serde default
let default_json = (entry.file_default_value_fn)();
if let Ok(default_value) = serde_json::from_str::<Value>(&default_json) {
if let Some(obj) = schema_value.as_object_mut() {
obj.insert("default".to_string(), default_value);
}
}
// Always overwrite description with the macro-provided one
if !entry.description.is_empty() {
if let Some(obj) = schema_value.as_object_mut() {
obj.insert(
"description".to_string(),
Value::String(entry.description.to_string()),
);
}
}
// Place the setting in the hierarchy
let target = if let Some(hierarchy) = entry.hierarchy {
ensure_hierarchy(&mut root_properties, hierarchy)
} else {
&mut root_properties
};
target.insert(entry.storage_key.to_string(), schema_value);
entry_count += 1;
}
// Collect $defs from the generator
let defs_map = generator.take_definitions(true);
// Assemble the root document
let mut root = Map::new();
root.insert(
"$schema".to_string(),
Value::String("https://json-schema.org/draft/2020-12/schema".to_string()),
);
root.insert(
"title".to_string(),
Value::String("Warp Settings".to_string()),
);
root.insert(
"description".to_string(),
Value::String(format!(
"JSON Schema for Warp settings ({channel} channel, {entry_count} settings)"
)),
);
root.insert("type".to_string(), Value::String("object".to_string()));
root.insert("properties".to_string(), Value::Object(root_properties));
if !defs_map.is_empty() {
root.insert("$defs".to_string(), Value::Object(defs_map));
}
// Strip type-derived numeric metadata (minimum, maximum, format) that
// schemars emits from Rust primitive bounds (e.g. u8 → max 255).
// These leak implementation details rather than semantic constraints.
let mut root_value = Value::Object(root);
strip_numeric_metadata(&mut root_value);
strip_empty_enum_entries(&mut root_value);
let output = serde_json::to_string_pretty(&root_value).expect("schema should serialize");
if let Some(path) = output_path {
let mut file = std::fs::File::create(path)
.unwrap_or_else(|e| panic!("Failed to create output file '{path}': {e}"));
file.write_all(output.as_bytes())
.unwrap_or_else(|e| panic!("Failed to write to '{path}': {e}"));
eprintln!("Wrote {entry_count} settings to {path}");
} else {
println!("{output}");
}
}
+63
View File
@@ -0,0 +1,63 @@
#[path = "channel_config.rs"]
mod channel_config;
use anyhow::Result;
use warp_core::{
channel::{Channel, ChannelState},
features,
};
fn main() -> Result<()> {
let config = channel_config::load_config!("local");
let mut state = ChannelState::new(Channel::Local, config)
.with_additional_features(features::DEBUG_FLAGS)
.with_additional_features(features::DOGFOOD_FLAGS)
.with_additional_features(features::PREVIEW_FLAGS);
// Enable sandbox telemetry feature flag if the env var is set.
if std::env::var("WITH_SANDBOX_TELEMETRY").is_ok() {
state = state.with_additional_features(&[features::FeatureFlag::WithSandboxTelemetry]);
}
ChannelState::set(state);
warp::run()
}
// If we're not using an external plist, embed the following as the Info.plist.
#[cfg(all(not(feature = "extern_plist"), target_os = "macos"))]
embed_plist::embed_info_plist_bytes!(r#"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDisplayName</key>
<string>WarpLocal</string>
<key>CFBundleExecutable</key>
<string>warp</string>
<key>CFBundleIdentifier</key>
<string>dev.warp.Warp-Local</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>WarpLocal</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.1.0</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.developer-tools</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>UIDesignRequiresCompatibility</key>
<true/>
<key>CFBundleURLTypes</key>
<array><dict><key>CFBundleURLName</key><string>Custom App</string><key>CFBundleURLSchemes</key><array><string>warplocal</string></array></dict></array>
<key>NSHumanReadableCopyright</key>
<string>© 2026, Denver Technologies, Inc</string>
</dict>
</plist>
"#.as_bytes());
+69
View File
@@ -0,0 +1,69 @@
// On Windows, we don't want to display a console window when the application is running in release
// builds. See https://doc.rust-lang.org/reference/runtime.html#the-windows_subsystem-attribute.
#![cfg_attr(feature = "release_bundle", windows_subsystem = "windows")]
use anyhow::Result;
use warp_core::{
channel::{Channel, ChannelConfig, ChannelState, OzConfig, WarpServerConfig},
AppId,
};
// Simple wrapper around warp::run() for Warp OSS builds.
fn main() -> Result<()> {
let mut state = ChannelState::new(
Channel::Oss,
ChannelConfig {
app_id: AppId::new("dev", "warp", "WarpOss"),
logfile_name: "warp-oss.log".into(),
server_config: WarpServerConfig::production(),
oz_config: OzConfig::production(),
telemetry_config: None,
crash_reporting_config: None,
autoupdate_config: None,
mcp_static_config: None,
},
);
if cfg!(debug_assertions) {
state = state.with_additional_features(warp_core::features::DEBUG_FLAGS);
}
ChannelState::set(state);
warp::run()
}
// If we're not using an external plist, embed the following as the Info.plist.
#[cfg(all(not(feature = "extern_plist"), target_os = "macos"))]
embed_plist::embed_info_plist_bytes!(r#"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDisplayName</key>
<string>WarpOss</string>
<key>CFBundleExecutable</key>
<string>warp-oss</string>
<key>CFBundleIdentifier</key>
<string>dev.warp.WarpOss</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>WarpOss</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.1.0</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.developer-tools</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>UIDesignRequiresCompatibility</key>
<true/>
<key>CFBundleURLTypes</key>
<array><dict><key>CFBundleURLName</key><string>Custom App</string><key>CFBundleURLSchemes</key><array><string>warposs</string></array></dict></array>
<key>NSHumanReadableCopyright</key>
<string>© 2026, Denver Technologies, Inc</string>
</dict>
</plist>
"#.as_bytes());
+23
View File
@@ -0,0 +1,23 @@
// On Windows, we don't want to display a console window when the application is running in release
// builds. See https://doc.rust-lang.org/reference/runtime.html#the-windows_subsystem-attribute.
#![cfg_attr(feature = "release_bundle", windows_subsystem = "windows")]
#[path = "channel_config.rs"]
mod channel_config;
use anyhow::Result;
use warp_core::{
channel::{Channel, ChannelState},
features,
};
// Simple wrapper around warp::run() for feature preview channel builds.
fn main() -> Result<()> {
ChannelState::set(
ChannelState::new(Channel::Preview, channel_config::load_config!("preview"))
.with_additional_features(features::PREVIEW_FLAGS)
.with_additional_features(&[features::FeatureFlag::ForceLogin]),
);
warp::run()
}
+19
View File
@@ -0,0 +1,19 @@
// On Windows, we don't want to display a console window when the application is running in release
// builds. See https://doc.rust-lang.org/reference/runtime.html#the-windows_subsystem-attribute.
#![cfg_attr(feature = "release_bundle", windows_subsystem = "windows")]
#[path = "channel_config.rs"]
mod channel_config;
use anyhow::Result;
use warp_core::channel::{Channel, ChannelState};
// Simple wrapper around warp::run() for stable channel builds.
fn main() -> Result<()> {
ChannelState::set(ChannelState::new(
Channel::Stable,
channel_config::load_config!("stable"),
));
warp::run()
}