feat(desktop): embed BoosAPI Desktop client as a subproject

Vendor the rebranded BoosAPI Desktop client (Tauri + Vue) into metapi as
a monorepo subdirectory under desktop/. Source only — node_modules,
dist, Cargo target and the upstream .git history are excluded.

desktop/ keeps its own independent Cargo workspace (desktop/src-tauri
with crates/*); it is not part of the backend boosapi crate, so a
`cargo check` at the metapi root still compiles only the backend. Build
the desktop app from desktop/src-tauri per desktop/README.md.

Note: app icons are still placeholder assets pending the final BoosAPI
logo. The updater signing keys live outside the repo and are not
included.
This commit is contained in:
boos
2026-06-22 11:32:57 +08:00
parent d9c78ecc73
commit e0a5f57793
2305 changed files with 449355 additions and 0 deletions
@@ -0,0 +1,181 @@
use open_agent_sdk::hooks::*;
use serde_json::json;
use std::sync::Arc;
#[tokio::test]
async fn test_hook_config_default() {
let config = HookConfig::default();
assert!(config.pre_tool_use.is_empty());
assert!(config.post_tool_use.is_empty());
assert!(config.post_sampling.is_empty());
assert!(config.stop.is_empty());
}
#[tokio::test]
async fn test_pre_tool_use_hook_allow() {
let config = HookConfig {
pre_tool_use: vec![HookRule {
matcher: "*".to_string(),
handler: Arc::new(|_input| {
Box::pin(async move {
HookOutput {
blocked: false,
message: None,
..Default::default()
}
})
}),
}],
..Default::default()
};
let result = config.run_pre_tool_use("Bash", &json!({})).await;
assert!(result.is_none()); // Not blocked
}
#[tokio::test]
async fn test_pre_tool_use_hook_block() {
let config = HookConfig {
pre_tool_use: vec![HookRule {
matcher: "Bash".to_string(),
handler: Arc::new(|_input| {
Box::pin(async move {
HookOutput {
blocked: true,
message: Some("Bash is blocked".to_string()),
..Default::default()
}
})
}),
}],
..Default::default()
};
let result = config.run_pre_tool_use("Bash", &json!({})).await;
assert!(result.is_some());
assert!(result.unwrap().blocked);
// Different tool should not be blocked
let result = config.run_pre_tool_use("Read", &json!({})).await;
assert!(result.is_none());
}
#[tokio::test]
async fn test_hook_matcher_wildcard() {
let config = HookConfig {
pre_tool_use: vec![HookRule {
matcher: "mcp__*".to_string(),
handler: Arc::new(|_input| {
Box::pin(async move {
HookOutput {
blocked: true,
message: Some("MCP blocked".to_string()),
..Default::default()
}
})
}),
}],
..Default::default()
};
let result = config
.run_pre_tool_use("mcp__server__tool", &json!({}))
.await;
assert!(result.is_some());
let result = config.run_pre_tool_use("Read", &json!({})).await;
assert!(result.is_none());
}
#[tokio::test]
async fn test_hook_matcher_pipe_or() {
let config = HookConfig {
pre_tool_use: vec![HookRule {
matcher: "Bash|Edit|Write".to_string(),
handler: Arc::new(|_input| {
Box::pin(async move {
HookOutput {
blocked: true,
message: None,
..Default::default()
}
})
}),
}],
..Default::default()
};
assert!(config
.run_pre_tool_use("Bash", &json!({}))
.await
.is_some());
assert!(config
.run_pre_tool_use("Edit", &json!({}))
.await
.is_some());
assert!(config
.run_pre_tool_use("Write", &json!({}))
.await
.is_some());
assert!(config
.run_pre_tool_use("Read", &json!({}))
.await
.is_none());
}
#[tokio::test]
async fn test_post_tool_use_hook() {
use std::sync::atomic::{AtomicBool, Ordering};
let called = Arc::new(AtomicBool::new(false));
let called_clone = called.clone();
let config = HookConfig {
post_tool_use: vec![HookRule {
matcher: "Bash".to_string(),
handler: Arc::new(move |_input| {
let called = called_clone.clone();
Box::pin(async move {
called.store(true, Ordering::SeqCst);
HookOutput::default()
})
}),
}],
..Default::default()
};
config
.run_post_tool_use("Bash", &json!({}), "output")
.await;
assert!(called.load(Ordering::SeqCst));
}
#[tokio::test]
async fn test_hook_input_fields() {
use std::sync::atomic::{AtomicBool, Ordering};
let verified = Arc::new(AtomicBool::new(false));
let verified_clone = verified.clone();
let config = HookConfig {
pre_tool_use: vec![HookRule {
matcher: "*".to_string(),
handler: Arc::new(move |input| {
let verified = verified_clone.clone();
Box::pin(async move {
assert_eq!(input.event, HookEvent::PreToolUse);
assert_eq!(input.tool_name.as_deref(), Some("Bash"));
assert!(input.tool_input.is_some());
verified.store(true, Ordering::SeqCst);
HookOutput::default()
})
}),
}],
..Default::default()
};
config
.run_pre_tool_use("Bash", &json!({"command": "ls"}))
.await;
assert!(verified.load(Ordering::SeqCst));
}