Commit Graph

2 Commits

  • .NET: [Breaking] Refactor AgentSkill API to async resource and script lookup (#6030)
    * .NET: Refactor AgentSkill API to async resource and script lookup
    
    Replace property-based AgentSkill.Content, Resources, and Scripts with
    async-by-name lookup methods plus boolean availability flags:
    
    - Content (string getter) -> GetContentAsync(CancellationToken)
    - Resources (full list) -> HasResources + GetResourceAsync(name, ct)
    - Scripts (full list) -> HasScripts + GetScriptAsync(name, ct)
    
    This makes the API friendlier for sources like MCP where enumerating all
    resources up front is expensive or impossible, and allows skill implementations
    to fetch content lazily.
    
    Subclass changes:
    - AgentFileSkill and AgentInlineSkill implement the new async API while
      preserving content caching.
    - AgentClassSkill<TSelf> keeps virtual Resources/Scripts properties for
      reflection-based discovery and seals the new HasResources/HasScripts/
      GetResourceAsync/GetScriptAsync overrides. Its previously non-thread-safe
      lazy initialization is replaced with Lazy<T> (default thread-safety) wired
      up in a new protected constructor, so concurrent first-access from multiple
      threads is safe.
    - AgentSkillsProvider calls the new async API and exposes 
    ead_skill_resource
      / load_skill / 
    un_skill_script tools that await the per-name lookups.
    
    Includes baseline CompatibilitySuppressions.xml entries for the removed
    property getters.
    
    Tests:
    - Direct coverage for HasResources, HasScripts, GetResourceAsync, and
      GetScriptAsync on all three skill implementations (positive, missing-name,
      and no-resources/no-scripts cases).
    - Thread-safety regression test for AgentClassSkill<TSelf> that exercises
      concurrent first-access to Resources, Scripts, and GetContentAsync from
      many tasks and asserts all observers see the same cached instance.
    - Provider-level coverage for the 
    ead_skill_resource tool (invocation +
      error paths) and for the previously untested error paths of load_skill
      and 
    un_skill_script (empty names, skill/resource/script not found).
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Address PR review comments
    
    - Move GetScriptAsync inside try/catch in RunSkillScriptAsync for error-handling parity
    - Remove dead _reflectedResources branch from AgentSkillTestExtensions
    - Fix XML docs to reference virtual Resources/Scripts properties (not sealed methods)
    - Add Async suffix to async test methods per naming convention
    - Make no-await tests synchronous to eliminate CS1998
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix formatting: add UTF-8 BOM and remove unused using
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix XML cref: Resources/Scripts are on AgentClassSkill<TSelf>
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Remove HasResources and HasScripts properties from AgentSkill
    
    Drop the virtual HasResources and HasScripts properties from AgentSkill
    and all concrete subclasses (AgentFileSkill, AgentInlineSkill,
    AgentClassSkill). AgentSkillsProvider now always includes all three
    tools (load_skill, read_skill_resource, run_skill_script) and both
    instruction blocks, since the tools already handle missing
    resources/scripts gracefully.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Add blank line for readability in file-based skills sample
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * Fix HostedAgentSkillsPatternTests for always-included tools
    
    Update assertions to expect read_skill_resource and run_skill_script
    tools are always present, matching the new behavior.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
  • .NET: Add Hosted-AgentSkills sample with Foundry Skills integration (#6013)
    * .NET: Add Hosted-AgentSkills sample for Foundry Skills integration
    
    Add a new hosted agent sample that demonstrates how to load behavioral
    guidelines from Foundry Skills at startup using AgentSkillsProvider and
    the progressive disclosure pattern (advertise -> load on demand).
    
    The sample:
    - Downloads SKILL.md files from Foundry via ProjectAgentSkills SDK
    - Extracts ZIP archives with zip-slip protection
    - Wires skills into AgentSkillsProvider as an AIContextProvider
    - Hosts the agent via the Responses protocol
    
    Ships two Contoso Outdoors skills matching the Python sample (PR #5822):
    - support-style: tone, formatting, signature guidelines
    - escalation-policy: when and how to escalate tickets
    
    Includes convenience provisioning gated behind PROVISION_SAMPLE_SKILLS
    env var, clearly documented as NOT a production pattern.
    
    Closes #5776
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * .NET: Add unit tests and integration test for Hosted-AgentSkills
    
    Unit tests (14 tests, all passing):
    - ZIP extraction with zip-slip guard (valid archive, traversal attack,
      sibling-prefix attack, directory entries)
    - Skill name validation (rejects dots, separators, traversal patterns)
    - AgentSkillsProvider with downloaded skills (advertises both skills,
      load_skill returns canary tokens, unknown skill returns error)
    
    Container integration test:
    - New 'agent-skills' scenario in the test container that creates
      Contoso Outdoors skills on disk and wires AgentSkillsProvider
    - AgentSkillsHostedAgentFixture + 4 integration tests verifying:
      - Routine questions load support-style skill (STYLE-CANARY-3318)
      - Escalation triggers load escalation-policy (ESC-CANARY-7742)
      - Skills are advertised in system prompt
      - load_skill tool is invoked via FunctionCallContent
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * .NET: Add smoke test, bootstrap, and docs for agent-skills integration
    
    - Add scripts/smoke.ps1 for local Docker smoke testing: builds the
      contributor image, runs the container, verifies both skills are loaded
      via canary tokens (STYLE-CANARY-3318, ESC-CANARY-7742)
    - Add 'agent-skills' to the bootstrap script scenario list
    - Add agent-skills row to the integration test README scenarios table
    - Exclude HostedAgentSkillsPatternTests from net472 (uses net8.0+ APIs)
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * .NET: Update commented-out package versions to latest across all hosted samples
    
    Update the end-user PackageReference versions (in the commented-out
    sections) from 1.0.0 to the current latest NuGet versions:
    
    - Microsoft.Agents.AI: 1.6.1
    - Microsoft.Agents.AI.Foundry: 1.6.1-preview.260514.1
    - Microsoft.Agents.AI.Foundry.Hosting: 1.6.1-preview.260514.1
    - Microsoft.Agents.AI.Hosting: 1.6.1-preview.260514.1
    - Microsoft.Agents.AI.OpenAI: 1.6.1
    - Microsoft.Agents.AI.Workflows: 1.6.1
    
    Also adds explicit versions to Hosted-Workflow-Handoff which had bare
    PackageReference entries without Version attributes.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * .NET: Fix broken markdown links in Hosted-AgentSkills README
    
    Remove references to non-existent ../../README.md. Replace with
    inline instructions matching other hosted samples that don't have
    a parent README.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    * .NET: Use OS-appropriate string comparison in zip-slip guard
    
    Use Ordinal on Unix (case-sensitive FS) and OrdinalIgnoreCase on
    Windows to prevent case-based path bypass on Linux containers.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>