// Copyright (c) Microsoft. All rights reserved.
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Shared.DiagnosticIds;
using Microsoft.Shared.Diagnostics;
namespace Microsoft.Agents.AI;
///
/// An discovered from a filesystem directory backed by a SKILL.md file.
///
[Experimental(DiagnosticIds.Experiments.AgentsAIExperiments)]
public sealed class AgentFileSkill : AgentSkill
{
private readonly IReadOnlyList _resources;
private readonly IReadOnlyList _scripts;
private readonly string _originalContent;
private string? _content;
///
/// Initializes a new instance of the class.
///
/// The parsed frontmatter metadata for this skill.
/// The full raw SKILL.md file content including YAML frontmatter.
/// Absolute path to the directory containing this skill.
/// Resources discovered for this skill.
/// Scripts discovered for this skill.
internal AgentFileSkill(
AgentSkillFrontmatter frontmatter,
string content,
string path,
IReadOnlyList? resources = null,
IReadOnlyList? scripts = null)
{
this.Frontmatter = Throw.IfNull(frontmatter);
this._originalContent = Throw.IfNull(content);
this.Path = Throw.IfNullOrWhitespace(path);
this._resources = resources ?? [];
this._scripts = scripts ?? [];
}
///
public override AgentSkillFrontmatter Frontmatter { get; }
///
///
/// Returns the raw SKILL.md content. When the skill has scripts, a
/// <script_schemas> block is appended describing the argument format.
/// The result is cached after the first access.
///
public override ValueTask GetContentAsync(CancellationToken cancellationToken = default)
{
var content = this._content ??= this._scripts is { Count: > 0 }
? this._originalContent + AgentInlineSkillContentBuilder.BuildScriptSchemasBlock(this._scripts)
: this._originalContent;
return new(content);
}
///
/// Gets the directory path where the skill was discovered.
///
public string Path { get; }
///
public override ValueTask GetResourceAsync(string name, CancellationToken cancellationToken = default)
{
var resource = this._resources.FirstOrDefault(r => r.Name == name);
return new(resource);
}
///
public override ValueTask GetScriptAsync(string name, CancellationToken cancellationToken = default)
{
var script = this._scripts.FirstOrDefault(s => s.Name == name);
return new(script);
}
}