package vip.mate.tool.disclosure;
import org.springframework.ai.tool.ToolCallback;
import vip.mate.agent.AgentToolSet;
import java.util.List;
import java.util.Set;
/**
* Splits an agent's tool set into the subset advertised to the LLM up front
* ({@code core} + already-enabled extensions) and the {@code extension} catalog
* that stays behind a stable progressive bridge. The model can invoke a
* deferred tool in the same action round through {@code tool_call}; legacy
* sessions may still activate one through {@code enable_tool}.
*
*
Tier is resolved per source: builtin / channel atomic tools from
* {@code mate_tool.disclosure_tier}, MCP tools from their owning
* {@code mate_mcp_server.disclosure_tier}. Tools that cannot be classified
* (ACP / dynamic-skill wrapped, plugin tools) default to {@code core} so the
* feature never hides a tool it does not understand.
*/
public interface ToolDisclosureService {
/** Resolve the tier of a runtime tool callback. */
DisclosureTier resolveTier(ToolCallback callback);
/** Resolve the tier of a tool by its function name. */
DisclosureTier resolveTierByName(String toolName);
/**
* Split {@code baseSet} into active callbacks (core ∪ enabled extensions)
* and the full extension catalog (every extension tool, enabled or not).
*/
ToolDisclosureSplit split(AgentToolSet baseSet, Set enabledExtensions);
/**
* Budget-aware variant: tools in {@code autoDemoted} are treated as
* extension tier for this split even when their resolved tier is core.
* The demotion set is decided once per agent build (see
* {@link #computeAutoDemotions}) so the runtime split, the baked catalog
* and the prompt-cache prefix stay consistent with each other.
*/
default ToolDisclosureSplit split(AgentToolSet baseSet, Set enabledExtensions,
Set autoDemoted) {
return split(baseSet, enabledExtensions);
}
/**
* Decide which core-tier tools to auto-demote so the advertised tool
* schemas fit {@code budgetTokens} (estimated). Ranking: never-used tools
* first, then least recently used; recovery/bridge meta-tools are never
* demoted. Empty when the set already fits, when
* {@code budgetTokens} is null, or in legacy disclosure mode.
*/
default Set computeAutoDemotions(AgentToolSet baseSet, Integer budgetTokens) {
return Set.of();
}
/**
* Render the {@code ## Extension Tools} system-prompt segment for the
* agent's extension tools, or an empty string when there are none / when
* disclosure is disabled.
*/
String renderExtensionCatalog(AgentToolSet baseSet, Integer maxInputTokens);
/**
* Budget-aware variant: auto-demoted tools are listed in the catalog too,
* so the model can discover and invoke them through {@code tool_call}.
*/
default String renderExtensionCatalog(AgentToolSet baseSet, Integer maxInputTokens,
Set autoDemoted) {
return renderExtensionCatalog(baseSet, maxInputTokens);
}
/** Drop the cached tier snapshot so the next resolve re-reads the DB. */
void invalidate();
/**
* Result of {@link #split}: {@code activeCallbacks} go to the LLM now;
* {@code extensionCatalog} is every extension tool (enabled or not), used to
* render the prompt catalog.
*/
record ToolDisclosureSplit(List activeCallbacks, List extensionCatalog) {
}
}