@@ -49,6 +49,11 @@ impl RegisteredController {
4949/// The global static registry of all controllers, initialized once on first access.
5050static REGISTRY : OnceLock < Vec < RegisteredController > > = OnceLock :: new ( ) ;
5151
52+ /// Internal-only controllers: registered for RPC dispatch but NOT in the agent-facing
53+ /// schema catalog. These handlers are callable by trusted callers (e.g. the Tauri scanner)
54+ /// but should not be advertised to agents via tool listings or schema discovery.
55+ static INTERNAL_REGISTRY : OnceLock < Vec < RegisteredController > > = OnceLock :: new ( ) ;
56+
5257/// The global static registry of standalone CLI adapters.
5358static CLI_ADAPTERS : OnceLock < Vec < RegisteredCliAdapter > > = OnceLock :: new ( ) ;
5459
@@ -69,6 +74,16 @@ fn registry() -> &'static [RegisteredController] {
6974 . as_slice ( )
7075}
7176
77+ /// Returns a reference to the internal-only controller registry.
78+ ///
79+ /// These controllers are callable over RPC but are NOT included in agent tool listings
80+ /// or schema discovery endpoints.
81+ fn internal_registry ( ) -> & ' static [ RegisteredController ] {
82+ INTERNAL_REGISTRY
83+ . get_or_init ( build_internal_only_controllers)
84+ . as_slice ( )
85+ }
86+
7287/// Returns a reference to the global CLI adapter registry.
7388fn cli_adapters ( ) -> & ' static [ RegisteredCliAdapter ] {
7489 CLI_ADAPTERS . get_or_init ( || {
@@ -192,6 +207,21 @@ fn build_registered_controllers() -> Vec<RegisteredController> {
192207 ) ;
193208 // Integration notification ingest, triage, and per-provider settings
194209 controllers. extend ( crate :: openhuman:: notifications:: all_notifications_registered_controllers ( ) ) ;
210+ // Structured WhatsApp Web data — agent-facing read-only controllers (list/search).
211+ // The write-path ingest controller is registered separately in build_internal_only_controllers.
212+ controllers. extend ( crate :: openhuman:: whatsapp_data:: all_whatsapp_data_registered_controllers ( ) ) ;
213+ controllers
214+ }
215+
216+ /// Aggregates controllers that are registered for RPC routing but NOT exposed to agents.
217+ ///
218+ /// These are write-path or internal-only handlers callable by trusted callers
219+ /// (e.g. the Tauri scanner ingest path) that should not appear in agent tool listings.
220+ fn build_internal_only_controllers ( ) -> Vec < RegisteredController > {
221+ let mut controllers = Vec :: new ( ) ;
222+ // whatsapp_data ingest: scanner-side write path. Callable over RPC by the
223+ // Tauri scanner but excluded from agent-facing schema discovery.
224+ controllers. extend ( crate :: openhuman:: whatsapp_data:: all_whatsapp_data_internal_controllers ( ) ) ;
195225 controllers
196226}
197227
@@ -255,6 +285,8 @@ fn build_declared_controller_schemas() -> Vec<ControllerSchema> {
255285 ) ;
256286 // Integration notification ingest, triage, and per-provider settings
257287 schemas. extend ( crate :: openhuman:: notifications:: all_notifications_controller_schemas ( ) ) ;
288+ // Structured WhatsApp Web data — local SQLite store, agent-queryable
289+ schemas. extend ( crate :: openhuman:: whatsapp_data:: all_whatsapp_data_controller_schemas ( ) ) ;
258290 schemas
259291}
260292
@@ -340,6 +372,9 @@ pub fn namespace_description(namespace: &str) -> Option<&'static str> {
340372 "Integration notification ingest, triage scoring, listing, read-state, \
341373 and per-provider routing settings.",
342374 ) ,
375+ "whatsapp_data" => Some (
376+ "Structured WhatsApp conversation and message store — list chats, read messages, and search across WhatsApp Web data." ,
377+ ) ,
343378 _ => None ,
344379 }
345380}
@@ -361,9 +396,13 @@ pub fn rpc_method_from_parts(namespace: &str, function: &str) -> Option<String>
361396}
362397
363398/// Retrieves the schema for a specific RPC method.
399+ ///
400+ /// Checks both the agent-facing registry and the internal registry so that
401+ /// parameter validation still applies to internal-only methods (e.g. ingest).
364402pub fn schema_for_rpc_method ( method : & str ) -> Option < ControllerSchema > {
365403 registry ( )
366404 . iter ( )
405+ . chain ( internal_registry ( ) . iter ( ) )
367406 . find ( |r| r. rpc_method_name ( ) == method)
368407 . map ( |r| r. schema . clone ( ) )
369408}
@@ -400,7 +439,11 @@ pub fn validate_params(
400439
401440/// Attempts to invoke a registered RPC method by name.
402441///
403- /// Returns `None` if the method is not found in the registry.
442+ /// Checks both the agent-facing controller registry and the internal-only registry,
443+ /// so scanner-side write paths (e.g. `openhuman.whatsapp_data_ingest`) are routable
444+ /// even though they are not included in agent tool listings.
445+ ///
446+ /// Returns `None` if the method is not found in either registry.
404447pub async fn try_invoke_registered_rpc (
405448 method : & str ,
406449 params : Map < String , Value > ,
@@ -410,6 +453,11 @@ pub async fn try_invoke_registered_rpc(
410453 return Some ( ( controller. handler ) ( params) . await ) ;
411454 }
412455 }
456+ for controller in internal_registry ( ) {
457+ if controller. rpc_method_name ( ) == method {
458+ return Some ( ( controller. handler ) ( params) . await ) ;
459+ }
460+ }
413461 None
414462}
415463
0 commit comments