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 — 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}