mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-26 23:59:58 -07:00
server: snapshot
This commit is contained in:
@@ -65,11 +65,9 @@ impl ApiRoutes for ApiRouter<AppState> {
|
||||
"/api.json",
|
||||
get_with(
|
||||
async |headers: HeaderMap,
|
||||
Extension(api_trimmed): Extension<Arc<String>>|
|
||||
Extension(api): Extension<Arc<ApiJson>>|
|
||||
-> Response {
|
||||
let value: serde_json::Value =
|
||||
serde_json::from_str(&api_trimmed).unwrap();
|
||||
Response::static_json(&headers, &value)
|
||||
Response::static_json(&headers, api.to_json())
|
||||
},
|
||||
|op| {
|
||||
op.id("get_api")
|
||||
|
||||
@@ -1,6 +1,23 @@
|
||||
use aide::openapi::OpenApi;
|
||||
use derive_more::Deref;
|
||||
use serde_json::{Map, Value};
|
||||
|
||||
/// Trims an OpenAPI spec JSON to reduce size for LLM consumption.
|
||||
/// Compact OpenAPI spec optimized for LLM consumption.
|
||||
#[derive(Deref)]
|
||||
pub struct ApiJson(String);
|
||||
|
||||
impl ApiJson {
|
||||
pub fn new(openapi: &OpenApi) -> Self {
|
||||
let json = serde_json::to_string(openapi).unwrap();
|
||||
Self(compact_json(&json))
|
||||
}
|
||||
|
||||
pub fn to_json(&self) -> serde_json::Value {
|
||||
serde_json::from_str(&self.0).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
/// Compacts an OpenAPI spec JSON to reduce size for LLM consumption.
|
||||
/// Removes redundant fields while preserving essential API information.
|
||||
///
|
||||
/// Transformations applied (in order):
|
||||
@@ -15,13 +32,13 @@ use serde_json::{Map, Value};
|
||||
/// 9. Remove format
|
||||
/// 10. Remove property descriptions
|
||||
/// 11. Simplify properties to direct types
|
||||
pub fn trim_openapi_json(json: &str) -> String {
|
||||
fn compact_json(json: &str) -> String {
|
||||
let mut spec: Value = serde_json::from_str(json).expect("Invalid OpenAPI JSON");
|
||||
trim_value(&mut spec);
|
||||
compact_value(&mut spec);
|
||||
serde_json::to_string(&spec).unwrap()
|
||||
}
|
||||
|
||||
fn trim_value(value: &mut Value) {
|
||||
fn compact_value(value: &mut Value) {
|
||||
match value {
|
||||
Value::Object(obj) => {
|
||||
// Step 1: Remove error responses
|
||||
@@ -106,12 +123,12 @@ fn trim_value(value: &mut Value) {
|
||||
|
||||
// Recurse into remaining values
|
||||
for (_, v) in obj.iter_mut() {
|
||||
trim_value(v);
|
||||
compact_value(v);
|
||||
}
|
||||
}
|
||||
Value::Array(arr) => {
|
||||
for item in arr {
|
||||
trim_value(item);
|
||||
compact_value(item);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@@ -298,7 +315,7 @@ mod tests {
|
||||
}
|
||||
}"##;
|
||||
|
||||
let result = trim_openapi_json(input);
|
||||
let result = compact_json(input);
|
||||
let parsed: Value = serde_json::from_str(&result).unwrap();
|
||||
|
||||
// Property should be simplified to array, not {"type": [...]}
|
||||
@@ -323,7 +340,7 @@ mod tests {
|
||||
}]
|
||||
}"##;
|
||||
|
||||
let result = trim_openapi_json(input);
|
||||
let result = compact_json(input);
|
||||
let parsed: Value = serde_json::from_str(&result).unwrap();
|
||||
|
||||
// Parameter should have type array including null
|
||||
@@ -344,7 +361,7 @@ mod tests {
|
||||
}
|
||||
}"##;
|
||||
|
||||
let result = trim_openapi_json(input);
|
||||
let result = compact_json(input);
|
||||
let parsed: Value = serde_json::from_str(&result).unwrap();
|
||||
|
||||
// Property with $ref should be simplified to just the type name
|
||||
@@ -372,7 +389,7 @@ mod tests {
|
||||
}
|
||||
}"##;
|
||||
|
||||
let result = trim_openapi_json(input);
|
||||
let result = compact_json(input);
|
||||
let parsed: Value = serde_json::from_str(&result).unwrap();
|
||||
|
||||
let props = &parsed["components"]["schemas"]["AddressStats"]["properties"];
|
||||
@@ -398,7 +415,7 @@ mod tests {
|
||||
}
|
||||
}"##;
|
||||
|
||||
let result = trim_openapi_json(input);
|
||||
let result = compact_json(input);
|
||||
let parsed: Value = serde_json::from_str(&result).unwrap();
|
||||
|
||||
assert_eq!(parsed["properties"]["address"], "Address");
|
||||
@@ -418,7 +435,7 @@ mod tests {
|
||||
}
|
||||
}"##;
|
||||
|
||||
let result = trim_openapi_json(input);
|
||||
let result = compact_json(input);
|
||||
let parsed: Value = serde_json::from_str(&result).unwrap();
|
||||
|
||||
// Array with $ref items should be simplified to "array[Type]"
|
||||
@@ -441,7 +458,7 @@ mod tests {
|
||||
}
|
||||
}"##;
|
||||
|
||||
let result = trim_openapi_json(input);
|
||||
let result = compact_json(input);
|
||||
let parsed: Value = serde_json::from_str(&result).unwrap();
|
||||
|
||||
assert_eq!(parsed["returns"], "Block");
|
||||
@@ -10,9 +10,9 @@
|
||||
// - https://api.supabase.com/api/v1
|
||||
//
|
||||
|
||||
mod trim;
|
||||
mod compact;
|
||||
|
||||
pub use trim::trim_openapi_json;
|
||||
pub use compact::ApiJson;
|
||||
|
||||
use aide::openapi::{Contact, Info, License, OpenApi, Tag};
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ impl Website {
|
||||
|
||||
// Try direct lookup, then with hash stripped
|
||||
let file = EMBEDDED_WEBSITE.get_file(path).or_else(|| {
|
||||
strip_importmap_hash(Path::new(path))
|
||||
ImportMap::strip_hash(Path::new(path))
|
||||
.and_then(|unhashed| EMBEDDED_WEBSITE.get_file(unhashed.to_str()?))
|
||||
});
|
||||
|
||||
@@ -146,7 +146,7 @@ impl Website {
|
||||
|
||||
// Try with hash stripped
|
||||
if !file_path.exists()
|
||||
&& let Some(unhashed) = strip_importmap_hash(&file_path)
|
||||
&& let Some(unhashed) = ImportMap::strip_hash(&file_path)
|
||||
&& unhashed.exists()
|
||||
{
|
||||
file_path = unhashed;
|
||||
@@ -171,23 +171,3 @@ impl Website {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Strip importmap hash from filename: `foo.abc12345.js` -> `foo.js`
|
||||
fn strip_importmap_hash(path: &Path) -> Option<PathBuf> {
|
||||
let stem = path.file_stem()?.to_str()?;
|
||||
let ext = path.extension()?.to_str()?;
|
||||
|
||||
if !matches!(ext, "js" | "mjs" | "css") {
|
||||
return None;
|
||||
}
|
||||
|
||||
let dot_pos = stem.rfind('.')?;
|
||||
let hash = &stem[dot_pos + 1..];
|
||||
|
||||
if hash.len() == 8 && hash.chars().all(|c| c.is_ascii_hexdigit()) {
|
||||
let name = &stem[..dot_pos];
|
||||
Some(path.with_file_name(format!("{}.{}", name, ext)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,8 +165,8 @@ impl Server {
|
||||
.javascript(workspace_root.join("modules/brk-client/index.js"))
|
||||
.python(workspace_root.join("packages/brk_client/brk_client/__init__.py"));
|
||||
|
||||
let openapi_json = Arc::new(serde_json::to_string(&openapi).unwrap());
|
||||
let openapi_trimmed = Arc::new(trim_openapi_json(&openapi_json));
|
||||
let api_json = Arc::new(ApiJson::new(&openapi));
|
||||
let openapi_json = serde_json::to_string(&openapi).unwrap();
|
||||
|
||||
let result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
|
||||
brk_bindgen::generate_clients(vecs, &openapi_json, &output_paths)
|
||||
@@ -180,7 +180,7 @@ impl Server {
|
||||
|
||||
let router = router
|
||||
.layer(Extension(Arc::new(openapi)))
|
||||
.layer(Extension(openapi_trimmed));
|
||||
.layer(Extension(api_json));
|
||||
|
||||
let service = NormalizePathLayer::trim_trailing_slash().layer(router);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user