001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.bean.mcp.v20260728;
018
019import static org.apache.juneau.commons.utils.CollectionUtils.*;
020import static org.apache.juneau.commons.utils.Shorts.*;
021
022import java.util.*;
023
024import org.apache.juneau.marshall.*;
025import org.apache.juneau.marshall.collections.*;
026
027/**
028 * Result of a {@code tools/call}, {@code prompts/get}, or {@code resources/read} handler pausing to request more
029 * input (MCP {@code 2026-07-28} SEP-2322 Multi-Round-Trip Requests).
030 *
031 * <p>
032 * Carries a server-assigned-id-keyed map of requested inputs ({@link #getInputRequests()}) and/or an opaque,
033 * tamper-evident continuation token ({@link #getRequestState()}). The pinned schema requires at least one of the
034 * two to be present; a caller must treat {@code requestState} as a black box, meaningful only to the codec that
035 * sealed it.
036 *
037 * <p>
038 * <b>{@code inputRequests} is lossless.</b> Each value is a full sub-request object exactly as the pinned schema
039 * models it (a sampling/roots/elicitation sub-request), typed as a raw {@link JsonMap} so a handler-supplied map
040 * reaches the wire byte-for-byte &mdash; there is no synthetic {@code {type, payload}} envelope, and no member is
041 * relocated or dropped. Concrete sub-request shapes are owned by the eventual consumers of this mechanism (C5
042 * sampling, C6 elicitation), neither of which is defined by this class. This mirrors the equally free-form shape
043 * of the request-side {@code inputResponses} map.
044 */
045@Marshalled
046public class InputRequiredResult extends Result<InputRequiredResult> {
047
048   private Map<String,JsonMap> inputRequests;
049   private String requestState;
050
051   /**
052    * Constructor. Sets {@code resultType} to {@code "input_required"}.
053    */
054   public InputRequiredResult() {
055      setResultType("input_required");
056   }
057
058   /**
059    * Server-assigned-id-keyed map of requested inputs.
060    *
061    * <p>
062    * Each value is a raw sub-request object (see the class Javadoc); it is carried losslessly, never wrapped in
063    * a synthetic envelope.
064    *
065    * @return The map, or {@code null} if not set.
066    */
067   public Map<String,JsonMap> getInputRequests() {
068      return u(inputRequests);
069   }
070
071   /**
072    * Sets the requested-inputs map.
073    *
074    * @param value The new value.  Can be <jk>null</jk> to unset the property.
075    * @return This object (for method chaining).
076    */
077   public InputRequiredResult setInputRequests(Map<String,JsonMap> value) {
078      inputRequests = value;
079      return this;
080   }
081
082   /**
083    * Convenience method to add a single requested-input entry.
084    *
085    * @param id The server-assigned id.  Can be <jk>null</jk> ({@link LinkedHashMap} tolerates a <jk>null</jk> key).
086    * @param value The raw sub-request object, carried to the wire byte-for-byte.  Can be <jk>null</jk> (stored
087    *    as <jk>null</jk>).
088    * @return This object (for method chaining).
089    */
090   public InputRequiredResult putInputRequest(String id, JsonMap value) {
091      if (inputRequests == null)
092         inputRequests = map();
093      inputRequests.put(id, value);
094      return this;
095   }
096
097   /**
098    * The opaque, tamper-evident continuation token.
099    *
100    * @return The token, or {@code null} if not set.
101    */
102   public String getRequestState() {
103      return requestState;
104   }
105
106   /**
107    * Sets the continuation token.
108    *
109    * @param value The new value.  Can be <jk>null</jk> to unset the property.
110    * @return This object (for method chaining).
111    */
112   public InputRequiredResult setRequestState(String value) {
113      requestState = value;
114      return this;
115   }
116
117   /**
118    * Validates the schema invariant that at least one of {@link #getInputRequests()} or
119    * {@link #getRequestState()} is present.
120    *
121    * @throws IllegalStateException If both are absent/empty.
122    */
123   public void validate() {
124      if (ie(inputRequests) && ie(requestState))
125         throw isex("InputRequiredResult requires at least one of inputRequests or requestState");
126   }
127}