From 5f167a463b9f4960521403cc3f57bc70c0b28223 Mon Sep 17 00:00:00 2001 From: Ytallo Layon Date: Fri, 3 Jul 2026 19:51:16 -0300 Subject: [PATCH] fix harness react schema publish --- harness/src/functions/mod.rs | 2 +- harness/src/functions/react.rs | 44 +++++++++++++++++++ harness/src/surface.rs | 3 ++ .../tests/golden/schemas/harness.react.json | 44 +++++++++++++++++++ harness/tests/schemas.rs | 1 + 5 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 harness/tests/golden/schemas/harness.react.json diff --git a/harness/src/functions/mod.rs b/harness/src/functions/mod.rs index 7a883eb3b..c23c594fa 100644 --- a/harness/src/functions/mod.rs +++ b/harness/src/functions/mod.rs @@ -214,7 +214,7 @@ pub fn register_all(iii: &Arc, deps: &Arc) { deps, react::REACT_ID, react::REACT_DESC, - |d, ev: Value, meta| async move { react::handle(&d, ev, meta).await }, + |d, ev: react::ReactEvent, meta| async move { react::handle(&d, ev.0, meta).await }, ); tracing::info!("all harness::* functions registered"); diff --git a/harness/src/functions/react.rs b/harness/src/functions/react.rs index 33dd9ff7e..e0c560a32 100644 --- a/harness/src/functions/react.rs +++ b/harness/src/functions/react.rs @@ -52,6 +52,50 @@ pub const REACT_DESC: &str = events and callbacks: bind it via engine::register_trigger with the sub-agent spec in \ `metadata`."; +/// Fired-event payload of a reactive subscription: arbitrary JSON produced by +/// the originating trigger, then appended to the spawned sub-agent task. +/// +/// The handler keeps a lossless `serde_json::Value` payload internally because +/// trigger events are not always objects. This wrapper exists so registration +/// publishes a real schema instead of `AnyValue`, which the registry publish +/// gate rejects. +#[derive(Debug, Clone, Deserialize)] +#[serde(transparent)] +pub struct ReactEvent(pub Value); + +impl JsonSchema for ReactEvent { + fn schema_name() -> String { + "ReactEvent".to_string() + } + + fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema { + use schemars::schema::{InstanceType, Metadata, SchemaObject}; + SchemaObject { + instance_type: Some( + vec![ + InstanceType::Null, + InstanceType::Boolean, + InstanceType::Number, + InstanceType::String, + InstanceType::Array, + InstanceType::Object, + ] + .into(), + ), + metadata: Some(Box::new(Metadata { + description: Some( + "Arbitrary fired-event payload from the subscribed trigger; appended to the \ + spawned sub-agent task." + .to_string(), + ), + ..Default::default() + })), + ..Default::default() + } + .into() + } +} + /// iii-state scope holding join accumulator records (one key per `join.id`). const JOIN_SCOPE: &str = "harness::react_join"; diff --git a/harness/src/surface.rs b/harness/src/surface.rs index 367cc445a..121205453 100644 --- a/harness/src/surface.rs +++ b/harness/src/surface.rs @@ -6,9 +6,11 @@ //! `harness::on-config-change`) are intentionally excluded — they are not part //! of the agent-facing surface. +use crate::functions::react::REACT_ID; use crate::functions::{ function_resolve::{FunctionResolveRequest, FunctionResolveResponse}, function_trigger::{FunctionTriggerRequest, FunctionTriggerResponse}, + react::{ReactEvent, ReactResult}, send::{SendRequest, SendResponse}, spawn::{SpawnRequest, SpawnResponse}, status::{StatusReport, StatusRequest}, @@ -62,5 +64,6 @@ pub fn catalog() -> Vec { spec::(FUNCTION_RESOLVE_ID), spec::(STOP_ID), spec::>(STATUS_ID), + spec::(REACT_ID), ] } diff --git a/harness/tests/golden/schemas/harness.react.json b/harness/tests/golden/schemas/harness.react.json new file mode 100644 index 000000000..4ebbbcde0 --- /dev/null +++ b/harness/tests/golden/schemas/harness.react.json @@ -0,0 +1,44 @@ +{ + "function_id": "harness::react", + "request_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Arbitrary fired-event payload from the subscribed trigger; appended to the spawned sub-agent task.", + "title": "ReactEvent", + "type": [ + "null", + "boolean", + "number", + "string", + "array", + "object" + ] + }, + "response_schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "child_session_id": { + "description": "The spawned sub-agent's child session id, when spawn returned one.", + "type": [ + "string", + "null" + ] + }, + "note": { + "description": "Why nothing spawned (missing spec, join not yet complete, already fired, error). Present iff `!spawned`.", + "type": [ + "string", + "null" + ] + }, + "spawned": { + "description": "Whether a `harness::spawn` was dispatched this call.", + "type": "boolean" + } + }, + "required": [ + "spawned" + ], + "title": "ReactResult", + "type": "object" + } +} diff --git a/harness/tests/schemas.rs b/harness/tests/schemas.rs index 4184252eb..8c9016df4 100644 --- a/harness/tests/schemas.rs +++ b/harness/tests/schemas.rs @@ -40,6 +40,7 @@ fn catalog_lists_all_functions_in_registration_order() { "harness::function::resolve", "harness::stop", "harness::status", + "harness::react", ] ); }