docs: comprehensive documentation for core Rust modules (#470)

* feat(core): enhance RPC controller and dispatch logic

- Added comprehensive documentation for the core RPC controller and dispatch modules, detailing their purpose and functionality.
- Introduced new functions for managing registered controllers and schemas, including validation and invocation methods.
- Improved the structure of the `RpcOutcome` type to standardize response formats across domain-specific handlers.
- Enhanced the local AI operations module with additional functionalities for agent interactions, model management, and audio processing.
- Updated the dispatcher to better route RPC calls to their respective handlers, ensuring a more robust and maintainable architecture.

These changes improve the clarity and usability of the RPC system, facilitating easier integration and interaction with various components of the OpenHuman platform.

* docs: comprehensive documentation for core Rust modules

* chore(dependencies): update OpenHuman to version 0.52.0 in Cargo.lock and add knip dependency in package.json
This commit is contained in:
Steven Enamakel
2026-04-09 16:17:53 -07:00
committed by GitHub
parent acc6246e59
commit 30eec2ad88
15 changed files with 815 additions and 42 deletions
Generated
+1 -1
View File
@@ -5120,7 +5120,7 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "openhuman"
version = "0.51.19"
version = "0.52.0"
dependencies = [
"aes-gcm",
"anyhow",
+3 -1
View File
@@ -43,7 +43,8 @@
"format": "prettier --write . && yarn rust:format",
"format:check": "prettier --check . && yarn rust:format:check",
"lint": "eslint . --ext .ts,.tsx",
"lint:fix": "eslint . --ext .ts,.tsx --fix"
"lint:fix": "eslint . --ext .ts,.tsx --fix",
"knip": "knip"
},
"dependencies": {
"@heroicons/react": "^2.2.0",
@@ -105,6 +106,7 @@
"eslint-plugin-react-hooks": "^7.0.1",
"husky": "^9.1.7",
"jsdom": "^28.0.0",
"knip": "^6.3.1",
"postcss": "^8.5.6",
"prettier": "^3.8.1",
"tailwindcss": "^3.4.19",
+40 -24
View File
@@ -64,10 +64,10 @@ fn user_id_from_object(obj: &serde_json::Map<String, Value>) -> Option<String> {
None
}
/// Best-effort user id from an authenticated profile payload.
/// Best-effort extraction of a user ID from an authenticated profile payload.
///
/// Accepts a raw user object or an envelope that nests the user under `data`
/// or `user`.
/// This function handles various envelope formats, including raw user objects
/// or those nested under `data` or `user` keys.
pub fn user_id_from_profile_payload(payload: &Value) -> Option<String> {
let obj = payload.as_object()?;
if let Some(data) = obj.get("data").and_then(|v| v.as_object()) {
@@ -85,14 +85,17 @@ pub fn user_id_from_profile_payload(payload: &Value) -> Option<String> {
})
}
/// Alias for [`user_id_from_profile_payload`] for semantic clarity in auth flows.
pub fn user_id_from_auth_me_payload(payload: &Value) -> Option<String> {
user_id_from_profile_payload(payload)
}
/// JSON body returned by the backend after OAuth connect starts.
/// JSON body returned by the backend when an OAuth connection process is initiated.
#[derive(Debug, Clone, Deserialize)]
pub struct ConnectResponse {
/// The URL to redirect the user to for OAuth authorization.
pub oauth_url: String,
/// The state parameter used to prevent CSRF and correlate the callback.
pub state: String,
}
@@ -117,12 +120,15 @@ struct IntegrationsData {
integrations: Vec<IntegrationSummary>,
}
/// Integration row from `GET /auth/integrations` (no tokens).
/// A summary of an active integration, as returned by the backend.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct IntegrationSummary {
/// Unique identifier for the integration.
pub id: String,
/// The name of the integration provider (e.g., "google", "slack").
pub provider: String,
/// RFC3339 timestamp of when the integration was created.
pub created_at: String,
}
@@ -149,16 +155,20 @@ struct LoginTokenConsumeData {
jwt_token: String,
}
/// Decrypted OAuth token payload from `POST /auth/integrations/:id/tokens`.
/// Decrypted OAuth token payload for handing off tokens to a local service or skill.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct IntegrationTokensHandoff {
/// The OAuth access token.
pub access_token: String,
/// The optional OAuth refresh token.
#[serde(default)]
pub refresh_token: Option<String>,
/// RFC3339 timestamp of when the access token expires.
pub expires_at: String,
}
/// A client for interacting with the TinyHumans / AlphaHuman backend API.
#[derive(Clone)]
pub struct BackendOAuthClient {
client: Client,
@@ -166,13 +176,14 @@ pub struct BackendOAuthClient {
}
impl BackendOAuthClient {
/// Creates a new `BackendOAuthClient` with the given API base URL.
pub fn new(api_base: &str) -> Result<Self> {
let base = Url::parse(api_base.trim()).context("Invalid API base URL")?;
let client = build_backend_reqwest_client()?;
Ok(Self { client, base })
}
/// `GET /auth/{provider}/login` — open in browser; Origin/Referer must be allowlisted on the server.
/// Returns the URL for initiating a login flow for a specific provider.
pub fn login_url(&self, provider: &str) -> Result<Url> {
let p = provider.trim().trim_matches('/');
anyhow::ensure!(!p.is_empty(), "provider is required");
@@ -181,7 +192,7 @@ impl BackendOAuthClient {
.context("build login URL")
}
/// `GET /auth/{provider}/connect` with Bearer JWT.
/// Initiates an OAuth connection flow for the current user and a specific provider.
pub async fn connect(
&self,
provider: &str,
@@ -236,7 +247,7 @@ impl BackendOAuthClient {
Ok(ConnectResponse { oauth_url, state })
}
/// `GET /auth/me` — current authenticated user profile for the Bearer session JWT.
/// Fetches the current authenticated user profile using the provided JWT.
pub async fn fetch_current_user(&self, bearer_jwt: &str) -> Result<Value> {
let url = self.base.join("auth/me").context("build /auth/me URL")?;
let resp = self
@@ -255,7 +266,7 @@ impl BackendOAuthClient {
parse_api_response_json(&text)
}
/// `POST /telegram/login-tokens/:token/consume` — exchange a one-time login token for a JWT.
/// Exchanges a one-time login token (e.g. from Telegram) for a long-lived JWT.
pub async fn consume_login_token(&self, login_token: &str) -> Result<String> {
let token = login_token.trim();
anyhow::ensure!(!token.is_empty(), "login token is required");
@@ -295,13 +306,13 @@ impl BackendOAuthClient {
Ok(jwt)
}
/// Confirms the JWT is accepted by the API using `GET /auth/me`.
/// Validates that the provided session token is still active and accepted.
pub async fn validate_session_token(&self, bearer_jwt: &str) -> Result<()> {
let _ = self.fetch_current_user(bearer_jwt).await?;
Ok(())
}
/// `POST /auth/channels/:channel/link-token` — create a short-lived channel link token.
/// Creates a short-lived link token for connecting a specific communication channel.
pub async fn create_channel_link_token(
&self,
channel: &str,
@@ -333,8 +344,7 @@ impl BackendOAuthClient {
parse_api_response_json(&text)
}
/// Generic authenticated JSON request helper for backend API routes that
/// follow the standard `{ success, data, message }` envelope.
/// Generic authenticated JSON request helper for backend API routes.
pub async fn authed_json(
&self,
bearer_jwt: &str,
@@ -374,7 +384,7 @@ impl BackendOAuthClient {
parse_api_response_json(&text)
}
/// `GET /auth/integrations`
/// Lists all active integrations for the current user.
pub async fn list_integrations(&self, bearer_jwt: &str) -> Result<Vec<IntegrationSummary>> {
let url = self
.base
@@ -401,7 +411,10 @@ impl BackendOAuthClient {
Ok(env.data.integrations)
}
/// `POST /auth/integrations/:id/tokens` — one-time handoff; decrypt with same key format as backend.
/// Fetches the decrypted OAuth tokens for a specific integration.
///
/// This is a one-time handoff process. The encryption key must match the
/// one used by the backend to encrypt the tokens.
pub async fn fetch_integration_tokens_handoff(
&self,
integration_id: &str,
@@ -441,7 +454,10 @@ impl BackendOAuthClient {
serde_json::from_str(&plaintext).context("parse decrypted token JSON")
}
/// `POST /auth/integrations/:id/client-key` — one-time handoff of client key share (deleted from Redis after retrieval).
/// Fetches the client key share for a specific integration.
///
/// This is a one-time handoff; the key is deleted from the backend's
/// temporary storage (Redis) after retrieval.
pub async fn fetch_client_key(&self, integration_id: &str, bearer_jwt: &str) -> Result<String> {
let id = integration_id.trim();
anyhow::ensure!(
@@ -487,7 +503,7 @@ impl BackendOAuthClient {
Ok(client_key.to_string())
}
/// `POST /channels/:channel/messages` — Send a rich message to a channel.
/// Sends a message to a communication channel.
pub async fn send_channel_message(
&self,
channel: &str,
@@ -506,7 +522,7 @@ impl BackendOAuthClient {
.await
}
/// `POST /channels/:channel/reactions` — React to a message in a channel.
/// Sends a reaction (e.g. emoji) to a message in a channel.
pub async fn send_channel_reaction(
&self,
channel: &str,
@@ -525,7 +541,7 @@ impl BackendOAuthClient {
.await
}
/// `POST /agent-integrations/tenor/search` — Search for GIFs via Tenor.
/// Searches for GIFs using the Tenor integration.
pub async fn search_tenor_gifs(
&self,
bearer_jwt: &str,
@@ -547,7 +563,7 @@ impl BackendOAuthClient {
.await
}
/// `POST /channels/:channel/threads` — Create a thread in a channel.
/// Creates a new thread in a communication channel.
pub async fn create_channel_thread(
&self,
channel: &str,
@@ -568,7 +584,7 @@ impl BackendOAuthClient {
.await
}
/// `PATCH /channels/:channel/threads/:thread_id` — Close or reopen a thread.
/// Updates an existing thread (e.g., closing or reopening it).
pub async fn update_channel_thread(
&self,
channel: &str,
@@ -595,7 +611,7 @@ impl BackendOAuthClient {
.await
}
/// `GET /channels/:channel/threads` — List threads, optionally filtered by active status.
/// Lists threads in a communication channel, optionally filtering by status.
pub async fn list_channel_threads(
&self,
channel: &str,
@@ -616,7 +632,7 @@ impl BackendOAuthClient {
self.authed_json(bearer_jwt, Method::GET, &path, None).await
}
/// `DELETE /auth/integrations/:id`
/// Revokes (deletes) an active integration.
pub async fn revoke_integration(&self, integration_id: &str, bearer_jwt: &str) -> Result<()> {
let id = integration_id.trim();
anyhow::ensure!(!id.is_empty(), "integration id is required");
+46
View File
@@ -1,3 +1,9 @@
//! Registry and dispatch logic for all OpenHuman controllers.
//!
//! This module serves as the central hub for registering domain-specific
//! controllers (e.g., memory, skills, config) and providing a unified
//! interface for both the CLI and RPC layers to invoke them.
use std::future::Future;
use std::pin::Pin;
use std::sync::OnceLock;
@@ -6,23 +12,37 @@ use serde_json::{Map, Value};
use crate::core::ControllerSchema;
/// A pinned, boxed future returned by a controller handler.
pub type ControllerFuture = Pin<Box<dyn Future<Output = Result<Value, String>> + Send + 'static>>;
/// A function pointer type for controller handlers.
///
/// Handlers take a map of parameters and return a [`ControllerFuture`].
pub type ControllerHandler = fn(Map<String, Value>) -> ControllerFuture;
/// A registered controller combining its schema and handler function.
#[derive(Clone)]
pub struct RegisteredController {
/// The schema defining the controller's identity and parameters.
pub schema: ControllerSchema,
/// The actual function that executes the controller's logic.
pub handler: ControllerHandler,
}
impl RegisteredController {
/// Returns the canonical RPC method name for this controller (e.g., `openhuman.memory_doc_put`).
pub fn rpc_method_name(&self) -> String {
rpc_method_name(&self.schema)
}
}
/// The global static registry of all controllers, initialized once on first access.
static REGISTRY: OnceLock<Vec<RegisteredController>> = OnceLock::new();
/// Returns a reference to the global controller registry.
///
/// This function initializes the registry if it hasn't been already,
/// performing validation to ensure no duplicates or missing handlers exist.
fn registry() -> &'static [RegisteredController] {
REGISTRY
.get_or_init(|| {
@@ -36,6 +56,7 @@ fn registry() -> &'static [RegisteredController] {
.as_slice()
}
/// Aggregates all controller implementations from across the codebase.
fn build_registered_controllers() -> Vec<RegisteredController> {
let mut controllers = Vec::new();
controllers.extend(crate::openhuman::about_app::all_about_app_registered_controllers());
@@ -79,6 +100,7 @@ fn build_registered_controllers() -> Vec<RegisteredController> {
controllers
}
/// Aggregates all controller schemas from across the codebase.
fn build_declared_controller_schemas() -> Vec<ControllerSchema> {
let mut schemas = Vec::new();
schemas.extend(crate::openhuman::about_app::all_about_app_controller_schemas());
@@ -119,19 +141,25 @@ fn build_declared_controller_schemas() -> Vec<ControllerSchema> {
schemas
}
/// Returns a vector of all currently registered controllers.
pub fn all_registered_controllers() -> Vec<RegisteredController> {
registry().to_vec()
}
/// Returns a vector of all currently declared controller schemas.
pub fn all_controller_schemas() -> Vec<ControllerSchema> {
let _ = registry();
build_declared_controller_schemas()
}
/// Generates a standardized RPC method name from a controller schema.
pub fn rpc_method_name(schema: &ControllerSchema) -> String {
format!("openhuman.{}_{}", schema.namespace, schema.function)
}
/// Returns a human-readable description for a given namespace.
///
/// This is used for CLI help output.
pub fn namespace_description(namespace: &str) -> Option<&'static str> {
match namespace {
"about_app" => Some("Catalog the app's user-facing capabilities and where to find them."),
@@ -171,6 +199,7 @@ pub fn namespace_description(namespace: &str) -> Option<&'static str> {
}
}
/// Looks up an RPC method name based on namespace and function.
pub fn rpc_method_from_parts(namespace: &str, function: &str) -> Option<String> {
registry()
.iter()
@@ -178,6 +207,7 @@ pub fn rpc_method_from_parts(namespace: &str, function: &str) -> Option<String>
.map(|r| r.rpc_method_name())
}
/// Retrieves the schema for a specific RPC method.
pub fn schema_for_rpc_method(method: &str) -> Option<ControllerSchema> {
registry()
.iter()
@@ -185,6 +215,11 @@ pub fn schema_for_rpc_method(method: &str) -> Option<ControllerSchema> {
.map(|r| r.schema.clone())
}
/// Validates that the provided parameters match the requirements of the controller schema.
///
/// # Errors
///
/// Returns an error message if required parameters are missing or if unknown parameters are provided.
pub fn validate_params(
schema: &ControllerSchema,
params: &Map<String, Value>,
@@ -210,6 +245,9 @@ pub fn validate_params(
Ok(())
}
/// Attempts to invoke a registered RPC method by name.
///
/// Returns `None` if the method is not found in the registry.
pub async fn try_invoke_registered_rpc(
method: &str,
params: Map<String, Value>,
@@ -222,6 +260,14 @@ pub async fn try_invoke_registered_rpc(
None
}
/// Validates the consistency of the controller registry.
///
/// Ensures that:
/// - There are no duplicate controllers or RPC methods.
/// - Every declared schema has a registered handler.
/// - Every registered handler has a declared schema.
/// - Namespaces and functions are not empty.
/// - Required input names are unique within a controller.
fn validate_registry(
registered: &[RegisteredController],
declared: &[ControllerSchema],
+27
View File
@@ -1,7 +1,26 @@
//! Central dispatcher for RPC requests.
//!
//! This module coordinates the routing of incoming requests to either the
//! core subsystem or the OpenHuman domain-specific handlers.
use crate::core::rpc_log;
use crate::core::types::{AppState, InvocationResult};
use serde_json::json;
/// Dispatches an RPC method call to the appropriate subsystem.
///
/// It first attempts to route the request to the core subsystem (e.g., `core.ping`).
/// If not found, it delegates to the `openhuman` domain-specific dispatcher.
///
/// # Arguments
///
/// * `state` - The current application state.
/// * `method` - The name of the RPC method to invoke.
/// * `params` - The parameters for the method call as a JSON value.
///
/// # Returns
///
/// A `Result` containing the JSON-formatted response or an error message.
pub async fn dispatch(
state: AppState,
method: &str,
@@ -13,10 +32,13 @@ pub async fn dispatch(
rpc_log::redact_params_for_log(&params)
);
// Try routing to internal core methods first.
if let Some(result) = try_core_dispatch(&state, method, params.clone()) {
log::debug!("[rpc:dispatch] routed method={} subsystem=core", method);
return result.map(crate::core::types::invocation_to_rpc_json);
}
// Delegate to the domain-specific dispatcher.
if let Some(result) = crate::rpc::try_dispatch(method, params).await {
log::debug!(
"[rpc:dispatch] routed method={} subsystem=openhuman",
@@ -29,6 +51,11 @@ pub async fn dispatch(
Err(format!("unknown method: {method}"))
}
/// Handles internal core-level RPC methods.
///
/// Currently supports:
/// - `core.ping`: Returns `{ "ok": true }`.
/// - `core.version`: Returns the current core version.
fn try_core_dispatch(
state: &AppState,
method: &str,
+38
View File
@@ -1,20 +1,34 @@
//! Shared core-level type definitions and response formats.
//!
//! This module contains structs and methods for handling RPC requests and
//! responses, as well as maintaining application state across subsystems.
use serde::{Deserialize, Serialize};
use serde_json::json;
/// Standard response structure for commands that include execution logs.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CommandResponse<T> {
/// The primary data returned by the command.
pub result: T,
/// A list of log messages generated during command execution.
pub logs: Vec<String>,
}
/// Success payload from a core RPC handler before JSON-RPC wrapping.
///
/// This internal type allows handlers to return a generic JSON value along
/// with optional logs.
#[derive(Debug, Clone)]
pub struct InvocationResult {
/// The value returned by the RPC function call.
pub value: serde_json::Value,
/// A list of execution logs.
pub logs: Vec<String>,
}
impl InvocationResult {
/// Creates a success result from any serializable value with no logs.
pub fn ok<T: Serialize>(v: T) -> Result<Self, String> {
Ok(Self {
value: serde_json::to_value(v).map_err(|e| e.to_string())?,
@@ -22,6 +36,7 @@ impl InvocationResult {
})
}
/// Creates a success result from a serializable value with accompanying logs.
pub fn with_logs<T: Serialize>(v: T, logs: Vec<String>) -> Result<Self, String> {
Ok(Self {
value: serde_json::to_value(v).map_err(|e| e.to_string())?,
@@ -30,6 +45,10 @@ impl InvocationResult {
}
}
/// Formats an [`InvocationResult`] into its standard JSON-RPC format.
///
/// If there are no logs, returns the value directly. Otherwise, returns an
/// object containing both `result` and `logs` keys.
pub fn invocation_to_rpc_json(inv: InvocationResult) -> serde_json::Value {
if inv.logs.is_empty() {
inv.value
@@ -38,38 +57,57 @@ pub fn invocation_to_rpc_json(inv: InvocationResult) -> serde_json::Value {
}
}
/// Standard JSON-RPC request format.
#[derive(Debug, Deserialize)]
pub struct RpcRequest {
/// The JSON-RPC version (e.g., `2.0`).
#[allow(dead_code)]
pub jsonrpc: String,
/// Unique identifier for the request, to be mirrored in the response.
pub id: serde_json::Value,
/// The name of the method to be invoked.
pub method: String,
/// Parameters for the method call. Defaults to null if not provided.
#[serde(default)]
pub params: serde_json::Value,
}
/// Standard JSON-RPC success response format.
#[derive(Debug, Serialize)]
pub struct RpcSuccess {
/// The JSON-RPC version (always `2.0`).
pub jsonrpc: &'static str,
/// The identifier mirrored from the original request.
pub id: serde_json::Value,
/// The result of the successful method invocation.
pub result: serde_json::Value,
}
/// Standard JSON-RPC error response format.
#[derive(Debug, Serialize)]
pub struct RpcFailure {
/// The JSON-RPC version (always `2.0`).
pub jsonrpc: &'static str,
/// The identifier mirrored from the original request.
pub id: serde_json::Value,
/// Information about the error that occurred.
pub error: RpcError,
}
/// Detail about an RPC invocation error.
#[derive(Debug, Serialize)]
pub struct RpcError {
/// Standardized error code (e.g., -32601 for Method not found).
pub code: i64,
/// A short, human-readable error message.
pub message: String,
/// Optional additional diagnostic data.
pub data: Option<serde_json::Value>,
}
/// Global core-level application state.
#[derive(Clone)]
pub struct AppState {
/// The current version of the OpenHuman core binary.
pub core_version: String,
}
+68 -1
View File
@@ -1,3 +1,10 @@
//! Core agent implementation for the OpenHuman platform.
//!
//! This module provides the `Agent` struct, which orchestrates the interaction
//! between the AI provider, available tools, memory systems, and the user.
//! It handles the agent's "turn" logic, including tool execution and history
//! management.
use super::dispatcher::{
NativeToolDispatcher, ParsedToolCall, ToolDispatcher, ToolExecutionResult, XmlToolDispatcher,
};
@@ -17,6 +24,11 @@ use anyhow::Result;
use std::io::Write as IoWrite;
use std::sync::Arc;
/// An autonomous or semi-autonomous AI agent.
///
/// The `Agent` is the central component that manages conversation state,
/// executes tools based on model requests, and interacts with the memory system
/// to maintain context across turns.
pub struct Agent {
provider: Box<dyn Provider>,
tools: Vec<Box<dyn Tool>>,
@@ -39,6 +51,7 @@ pub struct Agent {
learning_enabled: bool,
}
/// A builder for creating `Agent` instances with custom configuration.
pub struct AgentBuilder {
provider: Option<Box<dyn Provider>>,
tools: Option<Vec<Box<dyn Tool>>>,
@@ -66,6 +79,7 @@ impl Default for AgentBuilder {
}
impl AgentBuilder {
/// Creates a new `AgentBuilder` with default values.
pub fn new() -> Self {
Self {
provider: None,
@@ -88,56 +102,67 @@ impl AgentBuilder {
}
}
/// Sets the AI provider for the agent.
pub fn provider(mut self, provider: Box<dyn Provider>) -> Self {
self.provider = Some(provider);
self
}
/// Sets the available tools for the agent.
pub fn tools(mut self, tools: Vec<Box<dyn Tool>>) -> Self {
self.tools = Some(tools);
self
}
/// Sets the memory system for the agent.
pub fn memory(mut self, memory: Arc<dyn Memory>) -> Self {
self.memory = Some(memory);
self
}
/// Sets the system prompt builder for the agent.
pub fn prompt_builder(mut self, prompt_builder: SystemPromptBuilder) -> Self {
self.prompt_builder = Some(prompt_builder);
self
}
/// Sets the tool dispatcher for the agent.
pub fn tool_dispatcher(mut self, tool_dispatcher: Box<dyn ToolDispatcher>) -> Self {
self.tool_dispatcher = Some(tool_dispatcher);
self
}
/// Sets the memory loader for the agent.
pub fn memory_loader(mut self, memory_loader: Box<dyn MemoryLoader>) -> Self {
self.memory_loader = Some(memory_loader);
self
}
/// Sets the agent configuration.
pub fn config(mut self, config: crate::openhuman::config::AgentConfig) -> Self {
self.config = Some(config);
self
}
/// Sets the model name to use for chat requests.
pub fn model_name(mut self, model_name: String) -> Self {
self.model_name = Some(model_name);
self
}
/// Sets the temperature for chat requests.
pub fn temperature(mut self, temperature: f64) -> Self {
self.temperature = Some(temperature);
self
}
/// Sets the workspace directory for the agent.
pub fn workspace_dir(mut self, workspace_dir: std::path::PathBuf) -> Self {
self.workspace_dir = Some(workspace_dir);
self
}
/// Sets the identity configuration for the agent.
pub fn identity_config(
mut self,
identity_config: crate::openhuman::config::IdentityConfig,
@@ -146,16 +171,19 @@ impl AgentBuilder {
self
}
/// Sets the skills available to the agent.
pub fn skills(mut self, skills: Vec<crate::openhuman::skills::Skill>) -> Self {
self.skills = Some(skills);
self
}
/// Enables or disables automatic saving of conversation history to memory.
pub fn auto_save(mut self, auto_save: bool) -> Self {
self.auto_save = Some(auto_save);
self
}
/// Sets the query classification configuration.
pub fn classification_config(
mut self,
classification_config: crate::openhuman::config::QueryClassificationConfig,
@@ -164,21 +192,25 @@ impl AgentBuilder {
self
}
/// Sets the available model hints for auto-classification.
pub fn available_hints(mut self, available_hints: Vec<String>) -> Self {
self.available_hints = Some(available_hints);
self
}
/// Sets the post-turn hooks to be executed after each turn.
pub fn post_turn_hooks(mut self, hooks: Vec<Arc<dyn PostTurnHook>>) -> Self {
self.post_turn_hooks = hooks;
self
}
/// Enables or disables learning features.
pub fn learning_enabled(mut self, enabled: bool) -> Self {
self.learning_enabled = enabled;
self
}
/// Validates the configuration and builds the `Agent` instance.
pub fn build(self) -> Result<Agent> {
let tools = self
.tools
@@ -224,6 +256,10 @@ impl AgentBuilder {
}
impl Agent {
/// Injects unique IDs into tool calls that are missing them.
///
/// This is necessary for some tool dispatchers to correctly track and
/// associate results.
fn with_fallback_tool_call_ids(
mut parsed_calls: Vec<ParsedToolCall>,
iteration: usize,
@@ -236,6 +272,10 @@ impl Agent {
parsed_calls
}
/// Converts parsed tool calls into the provider-standard `ToolCall` format.
///
/// If the provider response already contains native tool calls, they are
/// returned as-is.
fn persisted_tool_calls_for_history(
response: &crate::openhuman::providers::ChatResponse,
parsed_calls: &[ParsedToolCall],
@@ -259,18 +299,25 @@ impl Agent {
.collect()
}
/// Returns a new `AgentBuilder`.
pub fn builder() -> AgentBuilder {
AgentBuilder::new()
}
/// Returns the current conversation history.
pub fn history(&self) -> &[ConversationMessage] {
&self.history
}
/// Clears the agent's conversation history.
pub fn clear_history(&mut self) {
self.history.clear();
}
/// Creates an `Agent` instance from a global configuration.
///
/// This is the primary way to initialize an agent with all system
/// integrations (memory, tools, skills, etc.) configured.
pub fn from_config(config: &Config) -> Result<Self> {
let runtime: Arc<dyn host_runtime::RuntimeAdapter> =
Arc::from(host_runtime::create_runtime(&config.runtime)?);
@@ -445,6 +492,10 @@ impl Agent {
.build()
}
/// Truncates the conversation history to the configured maximum message count.
///
/// System messages are always preserved. Older non-system messages are
/// dropped first.
fn trim_history(&mut self) {
let max = self.config.max_history_messages;
if self.history.len() <= max {
@@ -472,7 +523,10 @@ impl Agent {
self.history.extend(other_messages);
}
/// Pre-fetch learned context data from memory (async, non-blocking).
/// Pre-fetches learned context data from memory (observations, patterns, user profile).
///
/// This is an async, non-blocking operation that populates the context
/// for the system prompt.
async fn fetch_learned_context(&self) -> crate::openhuman::agent::prompt::LearnedContextData {
use crate::openhuman::agent::prompt::LearnedContextData;
@@ -524,6 +578,8 @@ impl Agent {
}
}
/// Builds the system prompt for the current turn, including tool
/// instructions and learned context.
fn build_system_prompt(
&self,
learned: crate::openhuman::agent::prompt::LearnedContextData,
@@ -571,6 +627,7 @@ impl Agent {
}
}
/// Executes a single tool call and returns the result and execution record.
async fn execute_tool_call(
&self,
call: &ParsedToolCall,
@@ -621,6 +678,7 @@ impl Agent {
(exec_result, record)
}
/// Executes multiple tool calls in sequence.
async fn execute_tools(
&self,
calls: &[ParsedToolCall],
@@ -635,6 +693,7 @@ impl Agent {
(results, records)
}
/// Classifies the user message to determine if a specific model hint should be used.
fn classify_model(&self, user_message: &str) -> String {
if let Some(hint) = super::classifier::classify(&self.classification_config, user_message) {
if self.available_hints.contains(&hint) {
@@ -645,6 +704,11 @@ impl Agent {
self.model_name.clone()
}
/// Performs a single interaction "turn" with the agent.
///
/// This is the core logic that takes user input, manages the history,
/// calls the LLM, handles tool calls (up to `max_tool_iterations`),
/// and returns the final assistant response.
pub async fn turn(&mut self, user_message: &str) -> Result<String> {
let turn_started = std::time::Instant::now();
log::info!(
@@ -864,10 +928,12 @@ impl Agent {
)
}
/// Runs a single turn with the given message and returns the response.
pub async fn run_single(&mut self, message: &str) -> Result<String> {
self.turn(message).await
}
/// Runs an interactive CLI loop, reading from standard input and printing to standard output.
pub async fn run_interactive(&mut self) -> Result<()> {
println!("🦀 OpenHuman Interactive Mode");
println!("Type /quit to exit.\n");
@@ -895,6 +961,7 @@ impl Agent {
}
}
/// Convenience entry point to run an agent with the given configuration and message.
pub async fn run(
config: Config,
message: Option<String>,
+42 -3
View File
@@ -9,6 +9,7 @@ use crate::openhuman::config::Config;
use crate::openhuman::screen_intelligence;
use crate::rpc::RpcOutcome;
/// Checks if an environment variable flag is enabled (e.g., "1", "true", "yes").
fn env_flag_enabled(key: &str) -> bool {
matches!(
std::env::var(key).ok().as_deref(),
@@ -16,6 +17,7 @@ fn env_flag_enabled(key: &str) -> bool {
)
}
/// Returns the core RPC URL from environment variables or a default value.
pub fn core_rpc_url_from_env() -> String {
std::env::var("OPENHUMAN_CORE_RPC_URL")
.unwrap_or_else(|_| "http://127.0.0.1:7788/rpc".to_string())
@@ -23,7 +25,10 @@ pub fn core_rpc_url_from_env() -> String {
const CONFIG_LOAD_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(30);
/// Loads persisted config with the same 30s timeout used by JSON-RPC and the core CLI.
/// Loads persisted config with a 30s timeout.
///
/// This is used by JSON-RPC and CLI handlers to ensure they don't hang
/// indefinitely if disk I/O is blocked.
pub async fn load_config_with_timeout() -> Result<Config, String> {
match tokio::time::timeout(CONFIG_LOAD_TIMEOUT, Config::load_or_init()).await {
Ok(Ok(config)) => Ok(config),
@@ -32,6 +37,7 @@ pub async fn load_config_with_timeout() -> Result<Config, String> {
}
}
/// Returns the default workspace directory fallback (~/.openhuman/workspace).
fn fallback_workspace_dir() -> PathBuf {
dirs::home_dir()
.unwrap_or_else(|| PathBuf::from("."))
@@ -39,16 +45,19 @@ fn fallback_workspace_dir() -> PathBuf {
.join("workspace")
}
/// Returns the default OpenHuman configuration directory (~/.openhuman).
fn default_openhuman_dir() -> PathBuf {
dirs::home_dir()
.unwrap_or_else(|| PathBuf::from("."))
.join(".openhuman")
}
/// Returns the path to the active workspace marker file.
fn active_workspace_marker_path(default_openhuman_dir: &Path) -> PathBuf {
default_openhuman_dir.join("active_workspace.toml")
}
/// Returns the parent directory of the config file.
fn config_openhuman_dir(config: &Config) -> PathBuf {
config
.config_path
@@ -56,6 +65,7 @@ fn config_openhuman_dir(config: &Config) -> PathBuf {
.map_or_else(|| PathBuf::from("."), PathBuf::from)
}
/// Internal helper to reset local data by removing specific directories and markers.
async fn reset_local_data_for_paths(
current_openhuman_dir: &Path,
default_openhuman_dir: &Path,
@@ -119,6 +129,7 @@ async fn reset_local_data_for_paths(
))
}
/// Serializes the current configuration into a JSON snapshot for the UI.
pub fn snapshot_config_json(config: &Config) -> Result<serde_json::Value, String> {
let value = serde_json::to_value(config).map_err(|e| e.to_string())?;
Ok(json!({
@@ -181,6 +192,7 @@ pub struct RuntimeFlagsOut {
pub log_prompts: bool,
}
/// Returns a full configuration snapshot for the UI.
pub async fn get_config_snapshot(config: &Config) -> Result<RpcOutcome<serde_json::Value>, String> {
let snapshot = snapshot_config_json(config)?;
Ok(RpcOutcome::new(
@@ -192,6 +204,7 @@ pub async fn get_config_snapshot(config: &Config) -> Result<RpcOutcome<serde_jso
))
}
/// Updates the model-related settings in the configuration.
pub async fn apply_model_settings(
config: &mut Config,
update: ModelSettingsPatch,
@@ -231,6 +244,7 @@ pub async fn apply_model_settings(
))
}
/// Updates the memory-related settings in the configuration.
pub async fn apply_memory_settings(
config: &mut Config,
update: MemorySettingsPatch,
@@ -261,6 +275,7 @@ pub async fn apply_memory_settings(
))
}
/// Updates the screen intelligence settings in the configuration.
pub async fn apply_screen_intelligence_settings(
config: &mut Config,
update: ScreenIntelligenceSettingsPatch,
@@ -311,6 +326,7 @@ pub async fn apply_screen_intelligence_settings(
))
}
/// Updates the runtime-related settings in the configuration.
pub async fn apply_runtime_settings(
config: &mut Config,
update: RuntimeSettingsPatch,
@@ -332,6 +348,7 @@ pub async fn apply_runtime_settings(
))
}
/// Updates the browser-related settings in the configuration.
pub async fn apply_browser_settings(
config: &mut Config,
update: BrowserSettingsPatch,
@@ -350,11 +367,13 @@ pub async fn apply_browser_settings(
))
}
/// Loads the configuration from disk and returns a snapshot.
pub async fn load_and_get_config_snapshot() -> Result<RpcOutcome<serde_json::Value>, String> {
let config = load_config_with_timeout().await?;
get_config_snapshot(&config).await
}
/// Loads the configuration, applies model settings updates, and saves it.
pub async fn load_and_apply_model_settings(
update: ModelSettingsPatch,
) -> Result<RpcOutcome<serde_json::Value>, String> {
@@ -362,6 +381,7 @@ pub async fn load_and_apply_model_settings(
apply_model_settings(&mut config, update).await
}
/// Loads the configuration, applies memory settings updates, and saves it.
pub async fn load_and_apply_memory_settings(
update: MemorySettingsPatch,
) -> Result<RpcOutcome<serde_json::Value>, String> {
@@ -369,6 +389,7 @@ pub async fn load_and_apply_memory_settings(
apply_memory_settings(&mut config, update).await
}
/// Loads the configuration, applies screen intelligence settings updates, and saves it.
pub async fn load_and_apply_screen_intelligence_settings(
update: ScreenIntelligenceSettingsPatch,
) -> Result<RpcOutcome<serde_json::Value>, String> {
@@ -376,6 +397,7 @@ pub async fn load_and_apply_screen_intelligence_settings(
apply_screen_intelligence_settings(&mut config, update).await
}
/// Loads the configuration, applies runtime settings updates, and saves it.
pub async fn load_and_apply_runtime_settings(
update: RuntimeSettingsPatch,
) -> Result<RpcOutcome<serde_json::Value>, String> {
@@ -383,6 +405,7 @@ pub async fn load_and_apply_runtime_settings(
apply_runtime_settings(&mut config, update).await
}
/// Updates the analytics-related settings in the configuration.
pub async fn apply_analytics_settings(
config: &mut Config,
update: AnalyticsSettingsPatch,
@@ -401,6 +424,7 @@ pub async fn apply_analytics_settings(
))
}
/// Loads the configuration, applies analytics settings updates, and saves it.
pub async fn load_and_apply_analytics_settings(
update: AnalyticsSettingsPatch,
) -> Result<RpcOutcome<serde_json::Value>, String> {
@@ -408,6 +432,7 @@ pub async fn load_and_apply_analytics_settings(
apply_analytics_settings(&mut config, update).await
}
/// Loads the configuration, applies browser settings updates, and saves it.
pub async fn load_and_apply_browser_settings(
update: BrowserSettingsPatch,
) -> Result<RpcOutcome<serde_json::Value>, String> {
@@ -415,13 +440,14 @@ pub async fn load_and_apply_browser_settings(
apply_browser_settings(&mut config, update).await
}
/// Resolves the effective API URL from configuration or defaults.
pub async fn load_and_resolve_api_url() -> Result<RpcOutcome<serde_json::Value>, String> {
let config = load_config_with_timeout().await?;
let resolved = crate::api::config::effective_api_url(&config.api_url);
Ok(RpcOutcome::new(json!({ "api_url": resolved }), Vec::new()))
}
/// Resolves workspace (load config or fallback), validates flag name, returns whether the flag file exists.
/// Resolves a workspace onboarding flag, creating or checking its existence.
pub async fn workspace_onboarding_flag_resolve(
flag_name: Option<String>,
default_name: &str,
@@ -442,6 +468,7 @@ pub async fn workspace_onboarding_flag_resolve(
workspace_onboarding_flag_exists(workspace_dir, trimmed)
}
/// Returns the current state of runtime-only flags.
pub fn get_runtime_flags() -> RpcOutcome<RuntimeFlagsOut> {
RpcOutcome::single_log(
RuntimeFlagsOut {
@@ -452,6 +479,7 @@ pub fn get_runtime_flags() -> RpcOutcome<RuntimeFlagsOut> {
)
}
/// Updates the `OPENHUMAN_BROWSER_ALLOW_ALL` environment flag.
pub fn set_browser_allow_all(enabled: bool) -> RpcOutcome<RuntimeFlagsOut> {
if enabled {
std::env::set_var("OPENHUMAN_BROWSER_ALLOW_ALL", "1");
@@ -465,6 +493,7 @@ pub fn set_browser_allow_all(enabled: bool) -> RpcOutcome<RuntimeFlagsOut> {
RpcOutcome::single_log(flags, "browser allow-all flag updated")
}
/// Checks if a specific onboarding flag file exists in the workspace.
pub fn workspace_onboarding_flag_exists(
workspace_dir: PathBuf,
flag_name: &str,
@@ -483,7 +512,7 @@ pub fn workspace_onboarding_flag_exists(
))
}
/// Creates or removes the workspace onboarding flag file.
/// Creates or removes an onboarding flag file in the workspace.
pub async fn workspace_onboarding_flag_set(
flag_name: Option<String>,
default_name: &str,
@@ -520,6 +549,7 @@ pub async fn workspace_onboarding_flag_set(
))
}
/// Returns whether the onboarding process has been marked as completed.
pub async fn get_onboarding_completed() -> Result<RpcOutcome<bool>, String> {
let config = load_config_with_timeout().await?;
Ok(RpcOutcome::single_log(
@@ -528,6 +558,7 @@ pub async fn get_onboarding_completed() -> Result<RpcOutcome<bool>, String> {
))
}
/// Updates and persists the onboarding completion status.
pub async fn set_onboarding_completed(value: bool) -> Result<RpcOutcome<bool>, String> {
let mut config = load_config_with_timeout().await?;
config.onboarding_completed = value;
@@ -540,6 +571,7 @@ pub async fn set_onboarding_completed(value: bool) -> Result<RpcOutcome<bool>, S
// ── Dictation settings ───────────────────────────────────────────────
/// Represents a partial update to dictation-related settings.
pub struct DictationSettingsPatch {
pub enabled: Option<bool>,
pub hotkey: Option<String>,
@@ -549,6 +581,7 @@ pub struct DictationSettingsPatch {
pub streaming_interval_ms: Option<u64>,
}
/// Returns the current dictation settings as a JSON object.
pub async fn get_dictation_settings() -> Result<RpcOutcome<serde_json::Value>, String> {
let config = load_config_with_timeout().await?;
let result = json!({
@@ -565,6 +598,7 @@ pub async fn get_dictation_settings() -> Result<RpcOutcome<serde_json::Value>, S
))
}
/// Loads configuration, applies dictation settings updates, and saves it.
pub async fn load_and_apply_dictation_settings(
update: DictationSettingsPatch,
) -> Result<RpcOutcome<serde_json::Value>, String> {
@@ -614,6 +648,7 @@ pub async fn load_and_apply_dictation_settings(
// ── Voice server settings ───────────────────────────────────────────
/// Represents a partial update to voice server related settings.
pub struct VoiceServerSettingsPatch {
pub auto_start: Option<bool>,
pub hotkey: Option<String>,
@@ -624,6 +659,7 @@ pub struct VoiceServerSettingsPatch {
pub custom_dictionary: Option<Vec<String>>,
}
/// Returns the current voice server settings as a JSON object.
pub async fn get_voice_server_settings() -> Result<RpcOutcome<serde_json::Value>, String> {
let config = load_config_with_timeout().await?;
let result = json!({
@@ -641,6 +677,7 @@ pub async fn get_voice_server_settings() -> Result<RpcOutcome<serde_json::Value>
))
}
/// Loads configuration, applies voice server settings updates, and saves it.
pub async fn load_and_apply_voice_server_settings(
update: VoiceServerSettingsPatch,
) -> Result<RpcOutcome<serde_json::Value>, String> {
@@ -691,6 +728,7 @@ pub async fn load_and_apply_voice_server_settings(
))
}
/// Returns the operational status of the agent server.
pub fn agent_server_status() -> RpcOutcome<serde_json::Value> {
let running = crate::openhuman::service::mock::mock_agent_running().unwrap_or(true);
log::info!("[config] agent_server_status requested: running={running}");
@@ -701,6 +739,7 @@ pub fn agent_server_status() -> RpcOutcome<serde_json::Value> {
RpcOutcome::single_log(payload, "agent server status checked")
}
/// Deletes all local data directories and workspace markers.
pub async fn reset_local_data() -> Result<RpcOutcome<serde_json::Value>, String> {
let config = load_config_with_timeout().await?;
let current_openhuman_dir = config_openhuman_dir(&config);
+42 -3
View File
@@ -1,4 +1,8 @@
//! JSON-RPC / CLI controller surface for the bundled local AI stack.
//!
//! This module provides high-level functions for interacting with local AI
//! services such as agent chat, model downloads, summarization, and
//! transcription. These functions are typically invoked via RPC or CLI.
use chrono::Utc;
use once_cell::sync::Lazy;
@@ -16,9 +20,21 @@ use crate::openhuman::local_ai::{
use crate::openhuman::providers::{self, ProviderRuntimeOptions};
use crate::rpc::RpcOutcome;
/// A static registry of active agent sessions for the REPL.
static REPL_AGENT_SESSIONS: Lazy<Mutex<HashMap<String, Agent>>> =
Lazy::new(|| Mutex::new(HashMap::new()));
/// Executes a single chat turn with an AI agent.
///
/// This function initializes an agent from the provided configuration and
/// processes the input message.
///
/// # Arguments
///
/// * `config` - The configuration used to build the agent. May be updated with model/temp overrides.
/// * `message` - The user message to process.
/// * `model_override` - Optional model name to use for this call.
/// * `temperature` - Optional sampling temperature override.
pub async fn agent_chat(
config: &mut Config,
message: &str,
@@ -36,6 +52,7 @@ pub async fn agent_chat(
Ok(RpcOutcome::single_log(response, "agent chat completed"))
}
/// A simplified chat interface that does not update the base configuration.
pub async fn agent_chat_simple(
config: &Config,
message: &str,
@@ -88,6 +105,7 @@ pub async fn agent_chat_simple(
))
}
/// Starts a persistent agent session for REPL interactions.
pub async fn agent_repl_session_start(
config: &Config,
session_id: Option<String>,
@@ -122,6 +140,7 @@ pub async fn agent_repl_session_start(
))
}
/// Resets the history of an active REPL session.
pub async fn agent_repl_session_reset(
session_id: &str,
) -> Result<RpcOutcome<serde_json::Value>, String> {
@@ -144,6 +163,7 @@ pub async fn agent_repl_session_reset(
))
}
/// Terminates an active REPL session.
pub async fn agent_repl_session_end(
session_id: &str,
) -> Result<RpcOutcome<serde_json::Value>, String> {
@@ -163,6 +183,7 @@ pub async fn agent_repl_session_end(
))
}
/// Returns the current operational status of the local AI stack.
pub async fn local_ai_status(
config: &Config,
) -> Result<RpcOutcome<local_ai::LocalAiStatus>, String> {
@@ -181,6 +202,7 @@ pub async fn local_ai_status(
))
}
/// Triggers a full download of all required local AI models.
pub async fn local_ai_download(
config: &Config,
force: bool,
@@ -202,6 +224,7 @@ pub async fn local_ai_download(
))
}
/// Triggers a download of all local AI assets and returns progress information.
pub async fn local_ai_download_all_assets(
config: &Config,
force: bool,
@@ -227,6 +250,7 @@ pub async fn local_ai_download_all_assets(
))
}
/// Generates a summary of the provided text using local AI models.
pub async fn local_ai_summarize(
config: &Config,
text: &str,
@@ -247,6 +271,7 @@ pub async fn local_ai_summarize(
))
}
/// Suggests relevant follow-up questions based on the provided context.
pub async fn local_ai_suggest_questions(
config: &Config,
context: Option<String>,
@@ -273,6 +298,7 @@ pub async fn local_ai_suggest_questions(
))
}
/// Executes a raw prompt directly against the local AI model.
pub async fn local_ai_prompt(
config: &Config,
prompt: &str,
@@ -291,6 +317,7 @@ pub async fn local_ai_prompt(
Ok(RpcOutcome::single_log(output, "local ai prompt completed"))
}
/// Executes a multimodal (vision) prompt with associated images.
pub async fn local_ai_vision_prompt(
config: &Config,
prompt: &str,
@@ -308,6 +335,7 @@ pub async fn local_ai_vision_prompt(
))
}
/// Generates semantic embeddings for the provided input strings.
pub async fn local_ai_embed(
config: &Config,
inputs: &[String],
@@ -323,6 +351,7 @@ pub async fn local_ai_embed(
))
}
/// Transcribes the audio file at the specified path.
pub async fn local_ai_transcribe(
config: &Config,
audio_path: &str,
@@ -338,6 +367,7 @@ pub async fn local_ai_transcribe(
))
}
/// Transcribes raw audio bytes by first saving them to a temporary file.
pub async fn local_ai_transcribe_bytes(
config: &Config,
audio_bytes: &[u8],
@@ -382,6 +412,7 @@ pub async fn local_ai_transcribe_bytes(
))
}
/// Performs text-to-speech synthesis and optionally saves the result to a file.
pub async fn local_ai_tts(
config: &Config,
text: &str,
@@ -395,6 +426,7 @@ pub async fn local_ai_tts(
Ok(RpcOutcome::single_log(output, "local ai tts completed"))
}
/// Returns the status of all local AI assets (models and support files).
pub async fn local_ai_assets_status(
config: &Config,
) -> Result<RpcOutcome<LocalAiAssetsStatus>, String> {
@@ -409,6 +441,7 @@ pub async fn local_ai_assets_status(
))
}
/// Returns progress for any ongoing asset downloads.
pub async fn local_ai_downloads_progress(
config: &Config,
) -> Result<RpcOutcome<LocalAiDownloadsProgress>, String> {
@@ -423,6 +456,7 @@ pub async fn local_ai_downloads_progress(
))
}
/// Triggers the download of a specific AI asset based on capability name.
pub async fn local_ai_download_asset(
config: &Config,
capability: &str,
@@ -438,12 +472,16 @@ pub async fn local_ai_download_asset(
))
}
/// A single message in a local AI chat conversation.
#[derive(Debug, serde::Deserialize)]
pub struct LocalAiChatMessage {
/// The role of the message sender (e.g., "user", "assistant").
pub role: String,
/// The text content of the message.
pub content: String,
}
/// Executes a multi-turn chat conversation using the local model.
pub async fn local_ai_chat(
config: &Config,
messages: Vec<LocalAiChatMessage>,
@@ -489,9 +527,10 @@ pub struct ReactionDecision {
pub emoji: Option<String>,
}
/// Ask the local model whether the assistant should add an emoji reaction to
/// the user's message, based on channel type and message content.
/// Designed to be called fire-and-forget — fast, lightweight, no cloud cost.
/// Evaluates whether the assistant should add an emoji reaction to a user message.
///
/// This uses the local model to make a quick decision based on the message
/// content and the channel context.
pub async fn local_ai_should_react(
config: &Config,
message: &str,
+73
View File
@@ -30,11 +30,15 @@ use std::path::{Component, Path, PathBuf};
// All access goes through `active_memory_client()` below.
/// Generates a unique request ID for memory operations.
///
/// This ID is used for tracing and logging purposes in the API response metadata.
fn memory_request_id() -> String {
uuid::Uuid::new_v4().to_string()
}
/// Converts an iterator of memory counts into a BTreeMap.
///
/// This is a convenience helper for populating the `counts` field in the API metadata.
fn memory_counts(
entries: impl IntoIterator<Item = (&'static str, usize)>,
) -> BTreeMap<String, usize> {
@@ -45,6 +49,8 @@ fn memory_counts(
}
/// Wraps data in an RPC API envelope.
///
/// This standardises the response format for memory-related RPC methods.
fn envelope<T: Serialize>(
data: T,
counts: Option<BTreeMap<String, usize>>,
@@ -67,6 +73,8 @@ fn envelope<T: Serialize>(
}
/// Wraps an error in an RPC API envelope.
///
/// This provides a consistent error reporting format for the memory system.
fn error_envelope<T: Serialize>(code: &str, message: String) -> RpcOutcome<ApiEnvelope<T>> {
RpcOutcome::new(
ApiEnvelope {
@@ -89,6 +97,8 @@ fn error_envelope<T: Serialize>(code: &str, message: String) -> RpcOutcome<ApiEn
}
/// Formats a floating-point timestamp as an RFC3339 string.
///
/// Returns `None` if the timestamp is invalid (NaN, infinite, or negative).
fn timestamp_to_rfc3339(timestamp: f64) -> Option<String> {
if !timestamp.is_finite() || timestamp < 0.0 {
return None;
@@ -113,6 +123,8 @@ fn memory_kind_label(kind: &MemoryItemKind) -> &'static str {
}
/// Generates a unique string identity for a graph relation.
///
/// The identity is composed of the namespace, subject, predicate, and object.
fn relation_identity(relation: &GraphRelationRecord) -> String {
format!(
"{}|{}|{}|{}",
@@ -482,127 +494,188 @@ async fn query_limit_for_request(
Ok(requested.max(total_documents))
}
/// Parameters for the `doc_put` RPC method.
#[derive(Debug, Deserialize)]
pub struct PutDocParams {
/// Namespace to store the document in.
pub namespace: String,
/// Unique key for the document within the namespace.
pub key: String,
/// Human-readable title for the document.
pub title: String,
/// The raw text content of the document.
pub content: String,
/// The source type of the document (e.g., "doc", "web").
#[serde(default = "default_source_type")]
pub source_type: String,
/// Priority level for retrieval (e.g., "high", "medium", "low").
#[serde(default = "default_priority")]
pub priority: String,
/// Optional tags for categorization and filtering.
#[serde(default)]
pub tags: Vec<String>,
/// Additional unstructured metadata.
#[serde(default)]
pub metadata: serde_json::Value,
/// Core category for the document (e.g., "core", "user").
#[serde(default = "default_category")]
pub category: String,
/// Optional session ID associated with the document.
#[serde(default)]
pub session_id: Option<String>,
/// Optional explicit document ID.
#[serde(default)]
pub document_id: Option<String>,
}
/// Parameters for the `doc_ingest` RPC method.
#[derive(Debug, Deserialize)]
pub struct IngestDocParams {
/// Namespace to store the document in.
pub namespace: String,
/// Unique key for the document within the namespace.
pub key: String,
/// Human-readable title for the document.
pub title: String,
/// The raw text content of the document.
pub content: String,
/// The source type of the document.
#[serde(default = "default_source_type")]
pub source_type: String,
/// Priority level for retrieval.
#[serde(default = "default_priority")]
pub priority: String,
/// Optional tags for the document.
#[serde(default)]
pub tags: Vec<String>,
/// Additional unstructured metadata.
#[serde(default)]
pub metadata: serde_json::Value,
/// Core category for the document.
#[serde(default = "default_category")]
pub category: String,
/// Optional session ID.
#[serde(default)]
pub session_id: Option<String>,
/// Optional explicit document ID.
#[serde(default)]
pub document_id: Option<String>,
/// Configuration for the ingestion process (chunking, etc.).
#[serde(default)]
pub config: Option<MemoryIngestionConfig>,
}
/// Parameters for RPC methods that only require a namespace.
#[derive(Debug, Deserialize)]
pub struct NamespaceOnlyParams {
/// The target namespace.
pub namespace: String,
}
/// Parameters for the `clear_namespace` RPC method.
#[derive(Debug, Deserialize)]
pub struct ClearNamespaceParams {
/// The namespace to clear.
pub namespace: String,
}
/// Result returned by the `clear_namespace` RPC method.
#[derive(Debug, Serialize)]
pub struct ClearNamespaceResult {
/// Whether the namespace was successfully cleared.
pub cleared: bool,
/// The namespace that was cleared.
pub namespace: String,
}
/// Parameters for the `doc_delete` RPC method.
#[derive(Debug, Deserialize)]
pub struct DeleteDocParams {
/// The namespace containing the document.
pub namespace: String,
/// The unique ID of the document to delete.
pub document_id: String,
}
/// Parameters for the `context_query` RPC method.
#[derive(Debug, Deserialize)]
pub struct QueryNamespaceParams {
/// The namespace to query.
pub namespace: String,
/// The natural language query string.
pub query: String,
/// Maximum number of results to return.
#[serde(default)]
pub limit: Option<u32>,
}
/// Parameters for the `context_recall` RPC method.
#[derive(Debug, Deserialize)]
pub struct RecallNamespaceParams {
/// The namespace to recall from.
pub namespace: String,
/// Maximum number of results to return.
#[serde(default)]
pub limit: Option<u32>,
}
/// Parameters for the `kv_set` RPC method.
#[derive(Debug, Deserialize)]
pub struct KvSetParams {
/// The namespace for the key-value pair.
#[serde(default)]
pub namespace: Option<String>,
/// The unique key.
pub key: String,
/// The value to store.
pub value: serde_json::Value,
}
/// Parameters for `kv_get` and `kv_delete` RPC methods.
#[derive(Debug, Deserialize)]
pub struct KvGetDeleteParams {
/// The namespace containing the key.
#[serde(default)]
pub namespace: Option<String>,
/// The unique key.
pub key: String,
}
/// Parameters for the `graph_upsert` RPC method.
#[derive(Debug, Deserialize)]
pub struct GraphUpsertParams {
/// The namespace for the relation.
#[serde(default)]
pub namespace: Option<String>,
/// The subject of the relation triple.
pub subject: String,
/// The predicate (relationship) of the triple.
pub predicate: String,
/// The object of the triple.
pub object: String,
/// Additional attributes for the relation.
#[serde(default)]
pub attrs: serde_json::Value,
}
/// Parameters for the `graph_query` RPC method.
#[derive(Debug, Deserialize)]
pub struct GraphQueryParams {
/// The namespace to query.
#[serde(default)]
pub namespace: Option<String>,
/// Optional subject filter.
#[serde(default)]
pub subject: Option<String>,
/// Optional predicate filter.
#[serde(default)]
pub predicate: Option<String>,
}
/// Result returned by the `doc_put` RPC method.
#[derive(Debug, Serialize)]
pub struct PutDocResult {
/// The unique ID of the upserted document.
pub document_id: String,
}
+8
View File
@@ -5,26 +5,31 @@ use crate::openhuman::service::daemon_host::DaemonHostConfig;
use crate::openhuman::service::{self, daemon_host, ServiceStatus};
use crate::rpc::RpcOutcome;
/// Installs the OpenHuman daemon as a system service.
pub async fn service_install(config: &Config) -> Result<RpcOutcome<ServiceStatus>, String> {
let status = service::install(config).map_err(|e| e.to_string())?;
Ok(RpcOutcome::single_log(status, "service install completed"))
}
/// Starts the installed OpenHuman daemon service.
pub async fn service_start(config: &Config) -> Result<RpcOutcome<ServiceStatus>, String> {
let status = service::start(config).map_err(|e| e.to_string())?;
Ok(RpcOutcome::single_log(status, "service start completed"))
}
/// Stops the running OpenHuman daemon service.
pub async fn service_stop(config: &Config) -> Result<RpcOutcome<ServiceStatus>, String> {
let status = service::stop(config).map_err(|e| e.to_string())?;
Ok(RpcOutcome::single_log(status, "service stop completed"))
}
/// Returns the current status of the OpenHuman daemon service.
pub async fn service_status(config: &Config) -> Result<RpcOutcome<ServiceStatus>, String> {
let status = service::status(config).map_err(|e| e.to_string())?;
Ok(RpcOutcome::single_log(status, "service status fetched"))
}
/// Requests an asynchronous restart of the core process.
pub async fn service_restart(
source: Option<String>,
reason: Option<String>,
@@ -32,6 +37,7 @@ pub async fn service_restart(
service::restart::service_restart(source, reason).await
}
/// Uninstalls the OpenHuman daemon system service.
pub async fn service_uninstall(config: &Config) -> Result<RpcOutcome<ServiceStatus>, String> {
let status = service::uninstall(config).map_err(|e| e.to_string())?;
Ok(RpcOutcome::single_log(
@@ -40,6 +46,7 @@ pub async fn service_uninstall(config: &Config) -> Result<RpcOutcome<ServiceStat
))
}
/// Reads the daemon host UI preferences from the configuration directory.
pub async fn daemon_host_get(config: &Config) -> Result<RpcOutcome<DaemonHostConfig>, String> {
let config_dir = config
.config_path
@@ -49,6 +56,7 @@ pub async fn daemon_host_get(config: &Config) -> Result<RpcOutcome<DaemonHostCon
Ok(RpcOutcome::single_log(current, "daemon host config loaded"))
}
/// Updates the daemon host UI preferences and saves them to disk.
pub async fn daemon_host_set(
config: &Config,
show_tray: bool,
+28
View File
@@ -1,3 +1,9 @@
//! Controller schemas and registration for the service domain.
//!
//! This module defines the transport-agnostic interface for service lifecycle
//! management (install, start, stop, etc.) and provides the mapping between
//! RPC methods and their underlying implementation handlers.
use serde::Deserialize;
use serde_json::{Map, Value};
@@ -6,6 +12,10 @@ use crate::core::{ControllerSchema, FieldSchema, TypeSchema};
use crate::openhuman::config::rpc as config_rpc;
use crate::rpc::RpcOutcome;
/// Returns a collection of all available controller schemas for the service domain.
///
/// These schemas describe the input parameters, output fields, and metadata for
/// every service-related RPC method.
pub fn all_controller_schemas() -> Vec<ControllerSchema> {
vec![
schemas("install"),
@@ -19,6 +29,10 @@ pub fn all_controller_schemas() -> Vec<ControllerSchema> {
]
}
/// Returns a collection of all registered controllers for the service domain.
///
/// Each `RegisteredController` pairs a `ControllerSchema` with its corresponding
/// async handler function.
pub fn all_registered_controllers() -> Vec<RegisteredController> {
vec![
RegisteredController {
@@ -56,6 +70,11 @@ pub fn all_registered_controllers() -> Vec<RegisteredController> {
]
}
/// Returns the specific `ControllerSchema` for a given service function.
///
/// # Arguments
///
/// * `function` - The name of the service function (e.g., "install", "restart").
pub fn schemas(function: &str) -> ControllerSchema {
match function {
"install" | "restart" | "start" | "stop" | "status" | "uninstall" => ControllerSchema {
@@ -153,6 +172,7 @@ fn handle_install(_params: Map<String, Value>) -> ControllerFuture {
})
}
/// Service controller for `service.start`.
fn handle_start(_params: Map<String, Value>) -> ControllerFuture {
Box::pin(async move {
let config = config_rpc::load_config_with_timeout().await?;
@@ -166,6 +186,8 @@ struct ServiceRestartParams {
reason: Option<String>,
}
/// Service controller for `service.restart`.
///
/// Service restart is intentionally config-free.
///
/// Unlike install/start/stop/status, the restart action targets the currently
@@ -181,6 +203,7 @@ fn handle_restart(params: Map<String, Value>) -> ControllerFuture {
})
}
/// Service controller for `service.stop`.
fn handle_stop(_params: Map<String, Value>) -> ControllerFuture {
Box::pin(async move {
let config = config_rpc::load_config_with_timeout().await?;
@@ -188,6 +211,7 @@ fn handle_stop(_params: Map<String, Value>) -> ControllerFuture {
})
}
/// Service controller for `service.status`.
fn handle_status(_params: Map<String, Value>) -> ControllerFuture {
Box::pin(async move {
let config = config_rpc::load_config_with_timeout().await?;
@@ -195,6 +219,7 @@ fn handle_status(_params: Map<String, Value>) -> ControllerFuture {
})
}
/// Service controller for `service.uninstall`.
fn handle_uninstall(_params: Map<String, Value>) -> ControllerFuture {
Box::pin(async move {
let config = config_rpc::load_config_with_timeout().await?;
@@ -207,6 +232,7 @@ struct DaemonHostSetParams {
show_tray: bool,
}
/// Service controller for `service.daemon_host_get`.
fn handle_daemon_host_get(_params: Map<String, Value>) -> ControllerFuture {
Box::pin(async move {
let config = config_rpc::load_config_with_timeout().await?;
@@ -214,6 +240,7 @@ fn handle_daemon_host_get(_params: Map<String, Value>) -> ControllerFuture {
})
}
/// Service controller for `service.daemon_host_set`.
fn handle_daemon_host_set(params: Map<String, Value>) -> ControllerFuture {
Box::pin(async move {
let payload: DaemonHostSetParams =
@@ -223,6 +250,7 @@ fn handle_daemon_host_set(params: Map<String, Value>) -> ControllerFuture {
})
}
/// Formats the RpcOutcome as an OpenHuman-standard JSON result.
fn to_json<T: serde::Serialize>(outcome: RpcOutcome<T>) -> Result<Value, String> {
outcome.into_cli_compatible_json()
}
+22
View File
@@ -1,16 +1,38 @@
//! Main dispatcher for domain-specific RPC methods.
//!
//! This module routes RPC calls to their respective domain handlers (e.g.,
//! security, memory, local AI). It serves as an extension point for
//! domain-level functionality in the OpenHuman platform.
use serde::Serialize;
use crate::rpc::RpcOutcome;
/// Helper to convert an [`RpcOutcome`] into a JSON value compatible with the CLI.
fn rpc_json<T: Serialize>(outcome: RpcOutcome<T>) -> Result<serde_json::Value, String> {
outcome.into_cli_compatible_json()
}
/// Dispatches an RPC method to its domain-specific handler.
///
/// If the method is recognized, it executes the handler and returns the
/// result wrapped in a `Some(Result)`. If not recognized, it returns `None`.
///
/// # Arguments
///
/// * `method` - The name of the RPC method to invoke.
/// * `params` - The parameters for the call as a JSON value.
///
/// # Returns
///
/// `Some(Ok(Value))` if successful, `Some(Err(String))` if the handler failed,
/// or `None` if the method was not found in this dispatcher.
pub async fn try_dispatch(
method: &str,
_params: serde_json::Value,
) -> Option<Result<serde_json::Value, String>> {
match method {
// Core security policy information.
"openhuman.security_policy_info" => Some(rpc_json(
crate::openhuman::security::rpc::security_policy_info(),
)),
+23 -4
View File
@@ -1,7 +1,11 @@
//! Shared types for JSON-RPC / CLI controller surfaces (`*/rpc.rs` in each domain).
//! Shared types for JSON-RPC / CLI controller surfaces.
//!
//! Domain `rpc` modules must not import `crate::core_server`; map to
//! [`crate::core_server::types::InvocationResult`] only in `core_server::dispatch`.
//! This module provides the foundational types and utilities for handling
//! RPC outcomes across different domain modules. It ensures a consistent
//! response format for both internal consumption and external presentation.
//!
//! Domain `rpc` modules should use [`RpcOutcome`] to wrap their results,
//! which facilitates consistent logging and error handling.
use serde::Serialize;
use serde_json::json;
@@ -11,19 +15,26 @@ mod dispatch;
pub use dispatch::try_dispatch;
/// Successful RPC handler result: serialized JSON value plus optional log lines.
///
/// This type represents the result of a domain-specific RPC call, including
/// any log messages generated during execution.
#[derive(Debug)]
pub struct RpcOutcome<T> {
/// The actual data returned by the RPC call.
pub value: T,
/// A collection of log messages for auditing or debugging.
pub logs: Vec<String>,
}
impl<T> RpcOutcome<T> {
/// Creates a new `RpcOutcome` with a value and a list of logs.
pub fn new(value: T, logs: Vec<String>) -> Self {
Self { value, logs }
}
}
impl<T: Serialize> RpcOutcome<T> {
/// Creates a new `RpcOutcome` with a value and a single log message.
pub fn single_log(value: T, log: impl Into<String>) -> Self {
Self {
value,
@@ -31,7 +42,15 @@ impl<T: Serialize> RpcOutcome<T> {
}
}
/// JSON shape matches the core CLI / `invocation_to_rpc_json` wrapper (`result` + `logs`).
/// Converts the outcome into a CLI-compatible JSON value.
///
/// The resulting JSON shape matches the core CLI expectations:
/// - If no logs are present, the value is returned directly.
/// - If logs are present, an object with `result` and `logs` keys is returned.
///
/// # Errors
///
/// Returns an error if serialization to JSON fails.
pub fn into_cli_compatible_json(self) -> Result<serde_json::Value, String> {
let RpcOutcome { value, logs } = self;
let value = serde_json::to_value(value).map_err(|e| e.to_string())?;
+354 -5
View File
@@ -916,6 +916,13 @@
"@jridgewell/resolve-uri" "^3.1.0"
"@jridgewell/sourcemap-codec" "^1.4.14"
"@napi-rs/wasm-runtime@^1.1.1":
version "1.1.3"
resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.3.tgz#1eeb8699770481306e5fcd84471f20fcb6177336"
integrity sha512-xK9sGVbJWYb08+mTJt3/YV24WxvxpXcXtP6B172paPZ+Ts69Re9dAr7lKwJoeIx8OoeuimEiRZ7umkiUVClmmQ==
dependencies:
"@tybys/wasm-util" "^0.10.1"
"@noble/curves@2.0.1":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-2.0.1.tgz#64ba8bd5e8564a02942655602515646df1cdb3ad"
@@ -954,6 +961,215 @@
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"
"@oxc-parser/binding-android-arm-eabi@0.121.0":
version "0.121.0"
resolved "https://registry.yarnpkg.com/@oxc-parser/binding-android-arm-eabi/-/binding-android-arm-eabi-0.121.0.tgz#a9440638713cdd6541f954a006558c85cc4f9b7c"
integrity sha512-n07FQcySwOlzap424/PLMtOkbS7xOu8nsJduKL8P3COGHKgKoDYXwoAHCbChfgFpHnviehrLWIPX0lKGtbEk/A==
"@oxc-parser/binding-android-arm64@0.121.0":
version "0.121.0"
resolved "https://registry.yarnpkg.com/@oxc-parser/binding-android-arm64/-/binding-android-arm64-0.121.0.tgz#e58da1d3983d9292d6d47598a6808f2c92a56ef4"
integrity sha512-/Dd1xIXboYAicw+twT2utxPD7bL8qh7d3ej0qvaYIMj3/EgIrGR+tSnjCUkiCT6g6uTC0neSS4JY8LxhdSU/sA==
"@oxc-parser/binding-darwin-arm64@0.121.0":
version "0.121.0"
resolved "https://registry.yarnpkg.com/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.121.0.tgz#0fb029403980e2f4470ff07e8385e3f2b01c7b01"
integrity sha512-A0jNEvv7QMtCO1yk205t3DWU9sWUjQ2KNF0hSVO5W9R9r/R1BIvzG01UQAfmtC0dQm7sCrs5puixurKSfr2bRQ==
"@oxc-parser/binding-darwin-x64@0.121.0":
version "0.121.0"
resolved "https://registry.yarnpkg.com/@oxc-parser/binding-darwin-x64/-/binding-darwin-x64-0.121.0.tgz#037cc978673883264ded01c912dbcefbd0302ca3"
integrity sha512-SsHzipdxTKUs3I9EOAPmnIimEeJOemqRlRDOp9LIj+96wtxZejF51gNibmoGq8KoqbT1ssAI5po/E3J+vEtXGA==
"@oxc-parser/binding-freebsd-x64@0.121.0":
version "0.121.0"
resolved "https://registry.yarnpkg.com/@oxc-parser/binding-freebsd-x64/-/binding-freebsd-x64-0.121.0.tgz#6dc183f7dc869a2475cb7e79af58967b3c6c4b64"
integrity sha512-v1APOTkCp+RWOIDAHRoaeW/UoaHF15a60E8eUL6kUQXh+i4K7PBwq2Wi7jm8p0ymID5/m/oC1w3W31Z/+r7HQw==
"@oxc-parser/binding-linux-arm-gnueabihf@0.121.0":
version "0.121.0"
resolved "https://registry.yarnpkg.com/@oxc-parser/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.121.0.tgz#a3108e318ce2e1654849c4ea7cfa87e66f22e8a3"
integrity sha512-PmqPQuqHZyFVWA4ycr0eu4VnTMmq9laOHZd+8R359w6kzuNZPvmmunmNJ8ybkm769A0nCoVp3TJ6dUz7B3FYIQ==
"@oxc-parser/binding-linux-arm-musleabihf@0.121.0":
version "0.121.0"
resolved "https://registry.yarnpkg.com/@oxc-parser/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.121.0.tgz#190df3a09f183055182c2f1635c8cc7296deeffb"
integrity sha512-vF24htj+MOH+Q7y9A8NuC6pUZu8t/C2Fr/kDOi2OcNf28oogr2xadBPXAbml802E8wRAVfbta6YLDQTearz+jw==
"@oxc-parser/binding-linux-arm64-gnu@0.121.0":
version "0.121.0"
resolved "https://registry.yarnpkg.com/@oxc-parser/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.121.0.tgz#9bba1a976350714f39f38a0f7fd01e2d2d090e88"
integrity sha512-wjH8cIG2Lu/3d64iZpbYr73hREMgKAfu7fqpXjgM2S16y2zhTfDIp8EQjxO8vlDtKP5Rc7waZW72lh8nZtWrpA==
"@oxc-parser/binding-linux-arm64-musl@0.121.0":
version "0.121.0"
resolved "https://registry.yarnpkg.com/@oxc-parser/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.121.0.tgz#7eb768a8551a78cf5388f0e24647b6f88914fb7c"
integrity sha512-qT663J/W8yQFw3dtscbEi9LKJevr20V7uWs2MPGTnvNZ3rm8anhhE16gXGpxDOHeg9raySaSHKhd4IGa3YZvuw==
"@oxc-parser/binding-linux-ppc64-gnu@0.121.0":
version "0.121.0"
resolved "https://registry.yarnpkg.com/@oxc-parser/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.121.0.tgz#f2fb9187417fab075d830098c4c87b48f8115365"
integrity sha512-mYNe4NhVvDBbPkAP8JaVS8lC1dsoJZWH5WCjpw5E+sjhk1R08wt3NnXYUzum7tIiWPfgQxbCMcoxgeemFASbRw==
"@oxc-parser/binding-linux-riscv64-gnu@0.121.0":
version "0.121.0"
resolved "https://registry.yarnpkg.com/@oxc-parser/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.121.0.tgz#534fe6c5054573fd06773b803e43777da70b96ca"
integrity sha512-+QiFoGxhAbaI/amqX567784cDyyuZIpinBrJNxUzb+/L2aBRX67mN6Jv40pqduHf15yYByI+K5gUEygCuv0z9w==
"@oxc-parser/binding-linux-riscv64-musl@0.121.0":
version "0.121.0"
resolved "https://registry.yarnpkg.com/@oxc-parser/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.121.0.tgz#a557ef48dce6bb6da1d0035d9fe203b21ff6fd51"
integrity sha512-9ykEgyTa5JD/Uhv2sttbKnCfl2PieUfOjyxJC/oDL2UO0qtXOtjPLl7H8Kaj5G7p3hIvFgu3YWvAxvE0sqY+hQ==
"@oxc-parser/binding-linux-s390x-gnu@0.121.0":
version "0.121.0"
resolved "https://registry.yarnpkg.com/@oxc-parser/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.121.0.tgz#a4779c98e0858af55a48a391e14fec6cc80941dd"
integrity sha512-DB1EW5VHZdc1lIRjOI3bW/wV6R6y0xlfvdVrqj6kKi7Ayu2U3UqUBdq9KviVkcUGd5Oq+dROqvUEEFRXGAM7EQ==
"@oxc-parser/binding-linux-x64-gnu@0.121.0":
version "0.121.0"
resolved "https://registry.yarnpkg.com/@oxc-parser/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.121.0.tgz#5c5ce9f1d4c37dd85943cd29089b87a79a3373f6"
integrity sha512-s4lfobX9p4kPTclvMiH3gcQUd88VlnkMTF6n2MTMDAyX5FPNRhhRSFZK05Ykhf8Zy5NibV4PbGR6DnK7FGNN6A==
"@oxc-parser/binding-linux-x64-musl@0.121.0":
version "0.121.0"
resolved "https://registry.yarnpkg.com/@oxc-parser/binding-linux-x64-musl/-/binding-linux-x64-musl-0.121.0.tgz#7c096e2ec6c53718f38acf4a0947efcfc30db565"
integrity sha512-P9KlyTpuBuMi3NRGpJO8MicuGZfOoqZVRP1WjOecwx8yk4L/+mrCRNc5egSi0byhuReblBF2oVoDSMgV9Bj4Hw==
"@oxc-parser/binding-openharmony-arm64@0.121.0":
version "0.121.0"
resolved "https://registry.yarnpkg.com/@oxc-parser/binding-openharmony-arm64/-/binding-openharmony-arm64-0.121.0.tgz#cb9aaa37e238648a0313016d6f7929b352ca7403"
integrity sha512-R+4jrWOfF2OAPPhj3Eb3U5CaKNAH9/btMveMULIrcNW/hjfysFQlF8wE0GaVBr81dWz8JLgQlsxwctoL78JwXw==
"@oxc-parser/binding-wasm32-wasi@0.121.0":
version "0.121.0"
resolved "https://registry.yarnpkg.com/@oxc-parser/binding-wasm32-wasi/-/binding-wasm32-wasi-0.121.0.tgz#e439fec1ea805979a2f75c8167a395568f20d6d6"
integrity sha512-5TFISkPTymKvsmIlKasPVTPuWxzCcrT8pM+p77+mtQbIZDd1UC8zww4CJcRI46kolmgrEX6QpKO8AvWMVZ+ifw==
dependencies:
"@napi-rs/wasm-runtime" "^1.1.1"
"@oxc-parser/binding-win32-arm64-msvc@0.121.0":
version "0.121.0"
resolved "https://registry.yarnpkg.com/@oxc-parser/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.121.0.tgz#9cbc2116b6f62387a2a5c205b08734c6f67d0104"
integrity sha512-V0pxh4mql4XTt3aiEtRNUeBAUFOw5jzZNxPABLaOKAWrVzSr9+XUaB095lY7jqMf5t8vkfh8NManGB28zanYKw==
"@oxc-parser/binding-win32-ia32-msvc@0.121.0":
version "0.121.0"
resolved "https://registry.yarnpkg.com/@oxc-parser/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.121.0.tgz#ac0ef57500be7e1af61241e0040d49cd6be1e597"
integrity sha512-4Ob1qvYMPnlF2N9rdmKdkQFdrq16QVcQwBsO8yiPZXof0fHKFF+LmQV501XFbi7lHyrKm8rlJRfQ/M8bZZPVLw==
"@oxc-parser/binding-win32-x64-msvc@0.121.0":
version "0.121.0"
resolved "https://registry.yarnpkg.com/@oxc-parser/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.121.0.tgz#142dadc748813ee0445a3a12003214ae28bf2c3f"
integrity sha512-BOp1KCzdboB1tPqoCPXgntgFs0jjeSyOXHzgxVFR7B/qfr3F8r4YDacHkTOUNXtDgM8YwKnkf3rE5gwALYX7NA==
"@oxc-project/types@^0.121.0":
version "0.121.0"
resolved "https://registry.yarnpkg.com/@oxc-project/types/-/types-0.121.0.tgz#85c497d5dea608212ac041d52c8dd69a0343359c"
integrity sha512-CGtOARQb9tyv7ECgdAlFxi0Fv7lmzvmlm2rpD/RdijOO9rfk/JvB1CjT8EnoD+tjna/IYgKKw3IV7objRb+aYw==
"@oxc-resolver/binding-android-arm-eabi@11.19.1":
version "11.19.1"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-android-arm-eabi/-/binding-android-arm-eabi-11.19.1.tgz#c44120aa5104e991e4a9969bb0b816263a6f4bc1"
integrity sha512-aUs47y+xyXHUKlbhqHUjBABjvycq6YSD7bpxSW7vplUmdzAlJ93yXY6ZR0c1o1x5A/QKbENCvs3+NlY8IpIVzg==
"@oxc-resolver/binding-android-arm64@11.19.1":
version "11.19.1"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-android-arm64/-/binding-android-arm64-11.19.1.tgz#bac86a9f2afda9cd6181ea1d1546448df579b740"
integrity sha512-oolbkRX+m7Pq2LNjr/kKgYeC7bRDMVTWPgxBGMjSpZi/+UskVo4jsMU3MLheZV55jL6c3rNelPl4oD60ggYmqA==
"@oxc-resolver/binding-darwin-arm64@11.19.1":
version "11.19.1"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-11.19.1.tgz#6bddb5b779cde0003dae0d703bf734e1536968f1"
integrity sha512-nUC6d2i3R5B12sUW4O646qD5cnMXf2oBGPLIIeaRfU9doJRORAbE2SGv4eW6rMqhD+G7nf2Y8TTJTLiiO3Q/dQ==
"@oxc-resolver/binding-darwin-x64@11.19.1":
version "11.19.1"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-11.19.1.tgz#055331438a73b21d357fdef947b9c06ec9046104"
integrity sha512-cV50vE5+uAgNcFa3QY1JOeKDSkM/9ReIcc/9wn4TavhW/itkDGrXhw9jaKnkQnGbjJ198Yh5nbX/Gr2mr4Z5jQ==
"@oxc-resolver/binding-freebsd-x64@11.19.1":
version "11.19.1"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-freebsd-x64/-/binding-freebsd-x64-11.19.1.tgz#735ebe53bad7e935255a0eb072f74a43ffb032c4"
integrity sha512-xZOQiYGFxtk48PBKff+Zwoym7ScPAIVp4c14lfLxizO2LTTTJe5sx9vQNGrBymrf/vatSPNMD4FgsaaRigPkqw==
"@oxc-resolver/binding-linux-arm-gnueabihf@11.19.1":
version "11.19.1"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-11.19.1.tgz#2072f679e5a8485f3c0fe98f3bd57dfd4647a19d"
integrity sha512-lXZYWAC6kaGe/ky2su94e9jN9t6M0/6c+GrSlCqL//XO1cxi5lpAhnJYdyrKfm0ZEr/c7RNyAx3P7FSBcBd5+A==
"@oxc-resolver/binding-linux-arm-musleabihf@11.19.1":
version "11.19.1"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-11.19.1.tgz#d74d0aa4738cc9f2af9e2015cbded0a5d34610dc"
integrity sha512-veG1kKsuK5+t2IsO9q0DErYVSw2azvCVvWHnfTOS73WE0STdLLB7Q1bB9WR+yHPQM76ASkFyRbogWo1GR1+WbQ==
"@oxc-resolver/binding-linux-arm64-gnu@11.19.1":
version "11.19.1"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-11.19.1.tgz#06aa9a330ecda461be6938969c1c4b67e969419e"
integrity sha512-heV2+jmXyYnUrpUXSPugqWDRpnsQcDm2AX4wzTuvgdlZfoNYO0O3W2AVpJYaDn9AG4JdM6Kxom8+foE7/BcSig==
"@oxc-resolver/binding-linux-arm64-musl@11.19.1":
version "11.19.1"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-11.19.1.tgz#e951cb96e7f72a8b83d6379d19d4e2624fca8d6e"
integrity sha512-jvo2Pjs1c9KPxMuMPIeQsgu0mOJF9rEb3y3TdpsrqwxRM+AN6/nDDwv45n5ZrUnQMsdBy5gIabioMKnQfWo9ew==
"@oxc-resolver/binding-linux-ppc64-gnu@11.19.1":
version "11.19.1"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-11.19.1.tgz#b73a3d95b9b7a74d8aa95ddefc06b6ab73d8afc6"
integrity sha512-vLmdNxWCdN7Uo5suays6A/+ywBby2PWBBPXctWPg5V0+eVuzsJxgAn6MMB4mPlshskYbppjpN2Zg83ArHze9gQ==
"@oxc-resolver/binding-linux-riscv64-gnu@11.19.1":
version "11.19.1"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-11.19.1.tgz#a9d29b7ddc351824ca25c4aa9de6cd45cffb5d1f"
integrity sha512-/b+WgR+VTSBxzgOhDO7TlMXC1ufPIMR6Vj1zN+/x+MnyXGW7prTLzU9eW85Aj7Th7CCEG9ArCbTeqxCzFWdg2w==
"@oxc-resolver/binding-linux-riscv64-musl@11.19.1":
version "11.19.1"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-11.19.1.tgz#0fcbb8ff0a09e1c61cbcd2a0803946aec0cb9b3b"
integrity sha512-YlRdeWb9j42p29ROh+h4eg/OQ3dTJlpHSa+84pUM9+p6i3djtPz1q55yLJhgW9XfDch7FN1pQ/Vd6YP+xfRIuw==
"@oxc-resolver/binding-linux-s390x-gnu@11.19.1":
version "11.19.1"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-11.19.1.tgz#1b7e32df63bf323e5ec765f536d2be14fba51787"
integrity sha512-EDpafVOQWF8/MJynsjOGFThcqhRHy417sRyLfQmeiamJ8qVhSKAn2Dn2VVKUGCjVB9C46VGjhNo7nOPUi1x6uA==
"@oxc-resolver/binding-linux-x64-gnu@11.19.1":
version "11.19.1"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-11.19.1.tgz#4ab2754f1b9521a3d0f00cb251d8b6603222f2f4"
integrity sha512-NxjZe+rqWhr+RT8/Ik+5ptA3oz7tUw361Wa5RWQXKnfqwSSHdHyrw6IdcTfYuml9dM856AlKWZIUXDmA9kkiBQ==
"@oxc-resolver/binding-linux-x64-musl@11.19.1":
version "11.19.1"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-11.19.1.tgz#91c3ae986004131726c78ba9aef6154daa9c238e"
integrity sha512-cM/hQwsO3ReJg5kR+SpI69DMfvNCp+A/eVR4b4YClE5bVZwz8rh2Nh05InhwI5HR/9cArbEkzMjcKgTHS6UaNw==
"@oxc-resolver/binding-openharmony-arm64@11.19.1":
version "11.19.1"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-openharmony-arm64/-/binding-openharmony-arm64-11.19.1.tgz#305fe66843f4ba2499fdacf1aac00341b5968198"
integrity sha512-QF080IowFB0+9Rh6RcD19bdgh49BpQHUW5TajG1qvWHvmrQznTZZjYlgE2ltLXyKY+qs4F/v5xuX1XS7Is+3qA==
"@oxc-resolver/binding-wasm32-wasi@11.19.1":
version "11.19.1"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-11.19.1.tgz#0e885eb1fd6e80582cf7dfb756647fbc427cce1b"
integrity sha512-w8UCKhX826cP/ZLokXDS6+milN8y4X7zidsAttEdWlVoamTNf6lhBJldaWr3ukTDiye7s4HRcuPEPOXNC432Vg==
dependencies:
"@napi-rs/wasm-runtime" "^1.1.1"
"@oxc-resolver/binding-win32-arm64-msvc@11.19.1":
version "11.19.1"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-11.19.1.tgz#2e14871c6075520ebfd312eb9c6a15e753237b90"
integrity sha512-nJ4AsUVZrVKwnU/QRdzPCCrO0TrabBqgJ8pJhXITdZGYOV28TIYystV1VFLbQ7DtAcaBHpocT5/ZJnF78YJPtQ==
"@oxc-resolver/binding-win32-ia32-msvc@11.19.1":
version "11.19.1"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-11.19.1.tgz#b684992dd0fc6e8f88053bfa86327b932e4cc486"
integrity sha512-EW+ND5q2Tl+a3pH81l1QbfgbF3HmqgwLfDfVithRFheac8OTcnbXt/JxqD2GbDkb7xYEqy1zNaVFRr3oeG8npA==
"@oxc-resolver/binding-win32-x64-msvc@11.19.1":
version "11.19.1"
resolved "https://registry.yarnpkg.com/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-11.19.1.tgz#a48dccdcb0833da4957579b0e314666407990364"
integrity sha512-6hIU3RQu45B+VNTY4Ru8ppFwjVS/S5qwYyGhBotmjxfEKk41I2DlGtRfGJndZ5+6lneE2pwloqunlOyZuX/XAw==
"@pkgjs/parseargs@^0.11.0":
version "0.11.0"
resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz"
@@ -1419,6 +1635,13 @@
resolved "https://registry.yarnpkg.com/@tweenjs/tween.js/-/tween.js-23.1.3.tgz#eff0245735c04a928bb19c026b58c2a56460539d"
integrity sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==
"@tybys/wasm-util@^0.10.1":
version "0.10.1"
resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.1.tgz#ecddd3205cf1e2d5274649ff0eedd2991ed7f414"
integrity sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==
dependencies:
tslib "^2.4.0"
"@types/aria-query@^5.0.1":
version "5.0.4"
resolved "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz"
@@ -3923,7 +4146,7 @@ fast-fifo@^1.2.0, fast-fifo@^1.3.2:
resolved "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz"
integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==
fast-glob@^3.3.2:
fast-glob@^3.3.2, fast-glob@^3.3.3:
version "3.3.3"
resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz"
integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==
@@ -3958,6 +4181,13 @@ fastq@^1.6.0:
dependencies:
reusify "^1.0.4"
fd-package-json@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/fd-package-json/-/fd-package-json-2.0.0.tgz#03f53ce5a0af552c2f4faf703a24e526310a2411"
integrity sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ==
dependencies:
walk-up-path "^4.0.0"
fd-slicer@~1.1.0:
version "1.1.0"
resolved "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz"
@@ -4052,6 +4282,13 @@ foreground-child@^3.1.0:
cross-spawn "^7.0.6"
signal-exit "^4.0.1"
formatly@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/formatly/-/formatly-0.3.0.tgz#5bb3b4e692f5a8c74ad8fe26154dd0a74aac6819"
integrity sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w==
dependencies:
fd-package-json "^2.0.0"
fraction.js@^5.3.4:
version "5.3.4"
resolved "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz"
@@ -4169,6 +4406,13 @@ get-symbol-description@^1.1.0:
es-errors "^1.3.0"
get-intrinsic "^1.2.6"
get-tsconfig@4.13.7:
version "4.13.7"
resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.13.7.tgz#b9d8b199b06033ceeea1a93df7ea5765415089bc"
integrity sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==
dependencies:
resolve-pkg-maps "^1.0.0"
get-tsconfig@^4.7.5:
version "4.13.6"
resolved "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.6.tgz"
@@ -4979,7 +5223,7 @@ jiti@^1.21.7:
resolved "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz"
integrity sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==
jiti@^2.6.1:
jiti@^2.6.0, jiti@^2.6.1:
version "2.6.1"
resolved "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz"
integrity sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==
@@ -5091,6 +5335,27 @@ keyv@^4.5.4:
dependencies:
json-buffer "3.0.1"
knip@^6.3.1:
version "6.3.1"
resolved "https://registry.yarnpkg.com/knip/-/knip-6.3.1.tgz#3cccdee10fe6a682171f0023d39ac1ed3edc0abc"
integrity sha512-22kLJloVcOVOAudCxlFOC0ICAMme7dKsS7pVTEnrmyKGpswb8ieznvAiSKUeFVDJhb01ect6dkDc1Ha1g1sPpg==
dependencies:
"@nodelib/fs.walk" "^1.2.3"
fast-glob "^3.3.3"
formatly "^0.3.0"
get-tsconfig "4.13.7"
jiti "^2.6.0"
minimist "^1.2.8"
oxc-parser "^0.121.0"
oxc-resolver "^11.19.1"
picocolors "^1.1.1"
picomatch "^4.0.1"
smol-toml "^1.6.1"
strip-json-comments "5.0.3"
unbash "^2.2.0"
yaml "^2.8.2"
zod "^4.1.11"
lazystream@^1.0.0:
version "1.0.1"
resolved "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz"
@@ -5668,7 +5933,7 @@ minimatch@^9.0.0, minimatch@^9.0.4, minimatch@^9.0.5:
dependencies:
brace-expansion "^2.0.1"
minimist@^1.2.0, minimist@^1.2.6:
minimist@^1.2.0, minimist@^1.2.6, minimist@^1.2.8:
version "1.2.8"
resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
@@ -5941,6 +6206,60 @@ own-keys@^1.0.1:
object-keys "^1.1.1"
safe-push-apply "^1.0.0"
oxc-parser@^0.121.0:
version "0.121.0"
resolved "https://registry.yarnpkg.com/oxc-parser/-/oxc-parser-0.121.0.tgz#da2670453eecf84863b48eccad353f365b7518bf"
integrity sha512-ek9o58+SCv6AV7nchiAcUJy1DNE2CC5WRdBcO0mF+W4oRjNQfPO7b3pLjTHSFECpHkKGOZSQxx3hk8viIL5YCg==
dependencies:
"@oxc-project/types" "^0.121.0"
optionalDependencies:
"@oxc-parser/binding-android-arm-eabi" "0.121.0"
"@oxc-parser/binding-android-arm64" "0.121.0"
"@oxc-parser/binding-darwin-arm64" "0.121.0"
"@oxc-parser/binding-darwin-x64" "0.121.0"
"@oxc-parser/binding-freebsd-x64" "0.121.0"
"@oxc-parser/binding-linux-arm-gnueabihf" "0.121.0"
"@oxc-parser/binding-linux-arm-musleabihf" "0.121.0"
"@oxc-parser/binding-linux-arm64-gnu" "0.121.0"
"@oxc-parser/binding-linux-arm64-musl" "0.121.0"
"@oxc-parser/binding-linux-ppc64-gnu" "0.121.0"
"@oxc-parser/binding-linux-riscv64-gnu" "0.121.0"
"@oxc-parser/binding-linux-riscv64-musl" "0.121.0"
"@oxc-parser/binding-linux-s390x-gnu" "0.121.0"
"@oxc-parser/binding-linux-x64-gnu" "0.121.0"
"@oxc-parser/binding-linux-x64-musl" "0.121.0"
"@oxc-parser/binding-openharmony-arm64" "0.121.0"
"@oxc-parser/binding-wasm32-wasi" "0.121.0"
"@oxc-parser/binding-win32-arm64-msvc" "0.121.0"
"@oxc-parser/binding-win32-ia32-msvc" "0.121.0"
"@oxc-parser/binding-win32-x64-msvc" "0.121.0"
oxc-resolver@^11.19.1:
version "11.19.1"
resolved "https://registry.yarnpkg.com/oxc-resolver/-/oxc-resolver-11.19.1.tgz#1b6b49812ae3469a2dcd10314444c2cb73a8d6a1"
integrity sha512-qE/CIg/spwrTBFt5aKmwe3ifeDdLfA2NESN30E42X/lII5ClF8V7Wt6WIJhcGZjp0/Q+nQ+9vgxGk//xZNX2hg==
optionalDependencies:
"@oxc-resolver/binding-android-arm-eabi" "11.19.1"
"@oxc-resolver/binding-android-arm64" "11.19.1"
"@oxc-resolver/binding-darwin-arm64" "11.19.1"
"@oxc-resolver/binding-darwin-x64" "11.19.1"
"@oxc-resolver/binding-freebsd-x64" "11.19.1"
"@oxc-resolver/binding-linux-arm-gnueabihf" "11.19.1"
"@oxc-resolver/binding-linux-arm-musleabihf" "11.19.1"
"@oxc-resolver/binding-linux-arm64-gnu" "11.19.1"
"@oxc-resolver/binding-linux-arm64-musl" "11.19.1"
"@oxc-resolver/binding-linux-ppc64-gnu" "11.19.1"
"@oxc-resolver/binding-linux-riscv64-gnu" "11.19.1"
"@oxc-resolver/binding-linux-riscv64-musl" "11.19.1"
"@oxc-resolver/binding-linux-s390x-gnu" "11.19.1"
"@oxc-resolver/binding-linux-x64-gnu" "11.19.1"
"@oxc-resolver/binding-linux-x64-musl" "11.19.1"
"@oxc-resolver/binding-openharmony-arm64" "11.19.1"
"@oxc-resolver/binding-wasm32-wasi" "11.19.1"
"@oxc-resolver/binding-win32-arm64-msvc" "11.19.1"
"@oxc-resolver/binding-win32-ia32-msvc" "11.19.1"
"@oxc-resolver/binding-win32-x64-msvc" "11.19.1"
p-limit@^3.0.2:
version "3.1.0"
resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz"
@@ -6164,6 +6483,11 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
picomatch@^4.0.1:
version "4.0.4"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.4.tgz#fd6f5e00a143086e074dffe4c924b8fb293b0589"
integrity sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==
picomatch@^4.0.2, picomatch@^4.0.3:
version "4.0.3"
resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz"
@@ -6979,6 +7303,11 @@ smart-buffer@^4.2.0:
resolved "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz"
integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==
smol-toml@^1.6.1:
version "1.6.1"
resolved "https://registry.yarnpkg.com/smol-toml/-/smol-toml-1.6.1.tgz#4fceb5f7c4b86c2544024ef686e12ff0983465be"
integrity sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==
socket.io-client@^4.8.3:
version "4.8.3"
resolved "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.3.tgz"
@@ -7268,6 +7597,11 @@ strip-indent@^3.0.0:
dependencies:
min-indent "^1.0.0"
strip-json-comments@5.0.3:
version "5.0.3"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-5.0.3.tgz#b7304249dd402ee67fd518ada993ab3593458bcf"
integrity sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==
strip-json-comments@^3.1.1:
version "3.1.1"
resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz"
@@ -7515,7 +7849,7 @@ tsconfig-paths@^3.15.0:
minimist "^1.2.6"
strip-bom "^3.0.0"
tslib@^2.0.1, tslib@^2.1.0:
tslib@^2.0.1, tslib@^2.1.0, tslib@^2.4.0:
version "2.8.1"
resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz"
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
@@ -7607,6 +7941,11 @@ typescript@~5.8.3:
resolved "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz"
integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==
unbash@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/unbash/-/unbash-2.2.0.tgz#ab65fcb3903aa5f2bc5ff8f057129ac2dd5bb2db"
integrity sha512-X2wH19RAPZE3+ldGicOkoj/SIA83OIxcJ6Cuaw23hf8Xc6fQpvZXY0SftE2JgS0QhYLUG4uwodSI3R53keyh7w==
unbox-primitive@^1.1.0:
version "1.1.0"
resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz"
@@ -7840,6 +8179,11 @@ wait-port@^1.1.0:
commander "^9.3.0"
debug "^4.3.4"
walk-up-path@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/walk-up-path/-/walk-up-path-4.0.0.tgz#590666dcf8146e2d72318164f1f2ac6ef51d4198"
integrity sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==
wcwidth@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz"
@@ -8097,6 +8441,11 @@ yallist@^3.0.2:
resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz"
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
yaml@^2.8.2:
version "2.8.3"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.8.3.tgz#a0d6bd2efb3dd03c59370223701834e60409bd7d"
integrity sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==
yargs-parser@^20.2.2, yargs-parser@^20.2.9:
version "20.2.9"
resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz"
@@ -8185,7 +8534,7 @@ zip-stream@^6.0.1:
resolved "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz"
integrity sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==
"zod@^3.25.0 || ^4.0.0":
"zod@^3.25.0 || ^4.0.0", zod@^4.1.11:
version "4.3.6"
resolved "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz"
integrity sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==