/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------------------------------------------*/
using System.Text.RegularExpressions;
namespace GitHub.Copilot;
///
/// Builder for /
/// using source-qualified filter
/// patterns (builtin:*, mcp:<name>, custom:*, etc.).
///
///
///
/// Tools are classified by the runtime at registration time (not from name
/// parsing), so AddBuiltIn("foo") matches only tools the runtime
/// registered as built-in, even if an MCP server or custom-agent extension
/// happens to register a tool with the same wire name.
///
///
/// inherits from List<string>, so instances
/// can be assigned directly to
/// or .
///
///
///
///
/// var session = await client.CreateSessionAsync(new SessionConfig
/// {
/// AvailableTools = new ToolSet()
/// .AddBuiltIn(BuiltInTools.Isolated)
/// .AddMcp("*")
/// .AddCustom("*"),
/// });
///
///
public sealed class ToolSet : List
{
private static readonly Regex s_validToolName = new(@"^[a-zA-Z0-9_-]+$", RegexOptions.Compiled);
///
/// Adds one or more built-in tool patterns.
///
/// A specific built-in tool name (e.g. "bash") or
/// "*" to match all built-in tools.
/// This for chaining.
public ToolSet AddBuiltIn(string name)
{
ValidateName("builtin", name);
Add($"builtin:{name}");
return this;
}
///
/// Adds a list of built-in tool patterns
/// (e.g. ).
///
/// Built-in tool names to add.
/// This for chaining.
public ToolSet AddBuiltIn(IEnumerable names)
{
ArgumentNullException.ThrowIfNull(names);
foreach (var name in names)
{
AddBuiltIn(name);
}
return this;
}
///
/// Adds a custom tool pattern. Matches tools registered via the SDK's
/// option or via custom agents.
///
/// A specific custom tool name or "*" to match
/// all custom tools.
/// This for chaining.
public ToolSet AddCustom(string name)
{
ValidateName("custom", name);
Add($"custom:{name}");
return this;
}
///
/// Adds an MCP tool pattern. Matches tools advertised by any configured
/// MCP server.
///
/// The runtime's canonical wire name for the MCP
/// tool (e.g. "github-list_issues"), or "*" to match all
/// MCP tools from any server.
/// This for chaining.
public ToolSet AddMcp(string toolName)
{
ValidateName("mcp", toolName);
Add($"mcp:{toolName}");
return this;
}
private static void ValidateName(string kind, string name)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentException(
$"Invalid {kind} tool name: must not be null or empty.",
nameof(name));
}
if (name == "*")
{
return;
}
if (!s_validToolName.IsMatch(name))
{
throw new ArgumentException(
$"Invalid {kind} tool name '{name}': tool names must match /^[a-zA-Z0-9_-]+$/ " +
"or be the wildcard '*'.",
nameof(name));
}
}
}
///
/// Curated sets of built-in tool names for common scenarios. Each constant is
/// meant to be passed to .
///
public static class BuiltInTools
{
///
/// Built-in tools that operate only within the bounds of a single session
/// — no host filesystem access outside the session, no cross-session
/// state, no host environment access, no network. Safe to enable in
/// scenarios (e.g. multi-tenant
/// servers) without leaking host capabilities.
///
///
///
/// Contract: tools in this set MUST NOT be extended (even behind
/// options or args) to read or write state outside the session boundary.
/// Adding cross-session or host-state behavior to one of these tools is a
/// breaking change that requires removing it from this set.
///
///
public static IReadOnlyList Isolated { get; } =
[
"ask_user",
"task_complete",
"exit_plan_mode",
"task",
"read_agent",
"write_agent",
"list_agents",
"send_inbox",
"context_board",
"skill",
];
}