From b397924020823aceaf177946a6440731985b2c2e Mon Sep 17 00:00:00 2001 From: Brian Demers Date: Fri, 27 Feb 2026 22:57:25 -0500 Subject: [PATCH] feat: add Java-friendly convenience methods for JsonValue and tool response output --- .../src/main/kotlin/dev/arcade/core/Values.kt | 36 +++++++++ .../arcade/models/tools/ExecuteToolRequest.kt | 8 ++ .../models/tools/ExecuteToolResponse.kt | 74 +++++++++++++++++++ 3 files changed, 118 insertions(+) diff --git a/arcade-java-core/src/main/kotlin/dev/arcade/core/Values.kt b/arcade-java-core/src/main/kotlin/dev/arcade/core/Values.kt index c20aeef..b997cd4 100644 --- a/arcade-java-core/src/main/kotlin/dev/arcade/core/Values.kt +++ b/arcade-java-core/src/main/kotlin/dev/arcade/core/Values.kt @@ -274,6 +274,42 @@ sealed class JsonValue : JsonField() { fun convert(type: Class): R? = JSON_MAPPER.convertValue(this, type) + // ------------------------------------------------------------------------- + // Start of manually added code + // ------------------------------------------------------------------------- + + /** + * Returns this value's map representation, or an empty map if this value is not a JSON object. + * + * Example usage: + * ```java + * Map map = jsonValue.toMapOrEmpty(); + * ``` + */ + fun toMapOrEmpty(): Map = + when (this) { + is JsonObject -> values + else -> emptyMap() + } + + /** + * Returns this value's list representation, or an empty list if this value is not a JSON array. + * + * Example usage: + * ```java + * List items = jsonValue.toListOrEmpty(); + * ``` + */ + fun toListOrEmpty(): List = + when (this) { + is JsonArray -> values + else -> emptyList() + } + + // ------------------------------------------------------------------------- + // End of manually added code + // ------------------------------------------------------------------------- + /** Returns the result of calling the [visitor] method corresponding to this value's variant. */ fun accept(visitor: Visitor): R = when (this) { diff --git a/arcade-java-core/src/main/kotlin/dev/arcade/models/tools/ExecuteToolRequest.kt b/arcade-java-core/src/main/kotlin/dev/arcade/models/tools/ExecuteToolRequest.kt index b21ce68..487040d 100644 --- a/arcade-java-core/src/main/kotlin/dev/arcade/models/tools/ExecuteToolRequest.kt +++ b/arcade-java-core/src/main/kotlin/dev/arcade/models/tools/ExecuteToolRequest.kt @@ -216,6 +216,9 @@ private constructor( /** JSON input to the tool, if any */ fun input(input: Input) = input(JsonField.of(input)) + /** JSON input to the tool, if any */ + fun input(input: Map) = input(Input.from(input)) + /** * Sets [Builder.input] to an arbitrary JSON value. * @@ -359,6 +362,11 @@ private constructor( /** Returns a mutable builder for constructing an instance of [Input]. */ @JvmStatic fun builder() = Builder() + + /** Converts a Map of input objects to an [Input] Map. */ + @JvmStatic + fun from(input: Map) = + Input(input.mapValues { (_, value) -> JsonValue.from(value) }) } /** A builder for [Input]. */ diff --git a/arcade-java-core/src/main/kotlin/dev/arcade/models/tools/ExecuteToolResponse.kt b/arcade-java-core/src/main/kotlin/dev/arcade/models/tools/ExecuteToolResponse.kt index 8a6fefd..eb5c67b 100644 --- a/arcade-java-core/src/main/kotlin/dev/arcade/models/tools/ExecuteToolResponse.kt +++ b/arcade-java-core/src/main/kotlin/dev/arcade/models/tools/ExecuteToolResponse.kt @@ -8,8 +8,10 @@ import com.fasterxml.jackson.annotation.JsonCreator import com.fasterxml.jackson.annotation.JsonProperty import dev.arcade.core.Enum import dev.arcade.core.ExcludeMissing +import dev.arcade.core.JsonArray import dev.arcade.core.JsonField import dev.arcade.core.JsonMissing +import dev.arcade.core.JsonObject import dev.arcade.core.JsonValue import dev.arcade.core.checkKnown import dev.arcade.core.checkRequired @@ -467,6 +469,78 @@ private constructor( */ @JsonProperty("value") @ExcludeMissing fun _value(): JsonValue = value + // ------------------------------------------------------------------------- + // Start of manually added code + // ------------------------------------------------------------------------- + + /** + * Returns an [Optional] containing the output value as a `Map`, or an + * empty [Optional] if the value is not a JSON object. + * + * Example usage: + * ```java + * Map result = response.output() + * .flatMap(Output::valueAsObject) + * .orElse(Map.of()); + * ``` + */ + fun valueAsObject(): Optional> = + when (value) { + is JsonObject -> Optional.of(value.values) + else -> Optional.empty() + } + + /** + * Returns the output value as a `Map`, or an empty map if the value is + * not a JSON object. + * + * Example usage: + * ```java + * Map result = output.valueAsObjectOrEmpty(); + * ``` + */ + fun valueAsObjectOrEmpty(): Map = + when (value) { + is JsonObject -> value.values + else -> emptyMap() + } + + /** + * Returns an [Optional] containing the output value as a `List`, or an empty + * [Optional] if the value is not a JSON array. + * + * Example usage: + * ```java + * List items = response.output() + * .flatMap(Output::valueAsArray) + * .orElse(List.of()); + * ``` + */ + fun valueAsArray(): Optional> = + when (value) { + is JsonArray -> Optional.of(value.values) + else -> Optional.empty() + } + + /** + * Returns the output value as a `List`, or an empty list if the value is not a + * JSON array. + * + * Example usage: + * ```java + * List items = output.valueAsArrayOrEmpty(); + * ``` + */ + fun valueAsArrayOrEmpty(): List = + when (value) { + is JsonArray -> value.values + else -> emptyList() + } + + // ------------------------------------------------------------------------- + // End of manually added code + // ------------------------------------------------------------------------- + /** * Returns the raw JSON value of [authorization]. *