AgentSkillsCN

create-provider-claude

为插件数据源生成提供者模式(接口加假实现/真实实现)。当用户说“为 [数据源] 创建提供者”、“为 [功能] 添加提供者接口”或“为 [插件] 实现提供者模式”时,此工具将大显身手。

SKILL.md
--- frontmatter
name: create-provider-claude
description: Generates the provider pattern (interface plus fake/real implementations) for plugin data sources. Use when the user says "create a provider for [data source]", "add provider interface for [feature]", or "implement provider pattern for [plugin]".

Create Provider Pattern

Generates provider interface and implementations under src/Plugins/Providers/. Follow project conventions from existing providers (e.g. IWeatherDataProvider, IOutlookEmailProvider).

Discovery (Ask First)

Before generating files, gather:

  1. Provider name and purpose

    • e.g. "Weather", "OutlookEmail", "Stock"
    • Use PascalCase; interface will be I[Name]DataProvider or I[Name]Provider if the domain is not "data" (e.g. IOutlookEmailProvider).
  2. Methods needed

    • Signature, parameters, return type (prefer Task<T> / Task<T?> for async).
    • For DTOs, define them in the same file as the interface (see OutlookEmail in IOutlookEmailProvider.cs).
  3. Which artifacts

    • Interface only
    • Interface + Fake
    • Interface + Real
    • Interface + Fake + Real (Both)

Only generate the Interface and the implementations the user requested.

File Layout and Namespaces

ArtifactPathNamespace
Interfacesrc/Plugins/Providers/Interfaces/I[Feature]DataProvider.csAnimalAI.Plugins.Providers
Fakesrc/Plugins/Providers/Fake/Fake[Feature]DataProvider.csAnimalAI.Plugins.Providers
Realsrc/Plugins/Providers/Real/Real[Feature]DataProvider.csAnimalAI.Plugins.Providers

Use I[Feature]DataProvider / Fake[Feature]DataProvider / Real[Feature]DataProvider unless the domain uses another suffix (e.g. IOutlookEmailProviderFakeOutlookEmailProvider, RealOutlookEmailProvider).

Interface Template

  • Namespace: AnimalAI.Plugins.Providers
  • XML summary on interface and on each method (params, returns)
  • Methods async: Task<T> or Task<T?>
  • Shared DTOs (e.g. OutlookEmail) in the same file as the interface when they are specific to that provider
csharp
namespace AnimalAI.Plugins.Providers;

/// <summary>
/// Interface for [purpose].
/// </summary>
public interface I[Feature]DataProvider
{
    /// <summary>[Description]</summary>
    /// <param name="...">...</param>
    /// <returns>...</returns>
    Task<ReturnType> MethodNameAsync(...);
}

Fake Provider Template

  • Implement the interface
  • No external calls; use in-memory data (e.g. Dictionary, static fields, or hard-coded lists)
  • Return immediately with Task.FromResult(...) for sync data, or Task.FromResult for trivial async
  • For “keyed” lookups (e.g. coordinates), round or normalize keys to match a small set of known mock keys; provide a sensible default for unknown keys
csharp
namespace AnimalAI.Plugins.Providers;

/// <summary>
/// Fake [feature] data provider that returns mock data for testing.
/// </summary>
public class Fake[Feature]DataProvider : I[Feature]DataProvider
{
    public Task<ReturnType> MethodNameAsync(...)
    {
        // Return mock data; use Task.FromResult(...) if no real async work
        return Task.FromResult(...);
    }
}

Real Provider Template

  • Implement the interface
  • Use HttpClient / HttpClient.GetFromJsonAsync or other real I/O as needed
  • Keep DTOs (e.g. for JSON) in the same file as private classes with [JsonPropertyName("...")] if required
  • Swallow or log errors and return null or a safe default per existing convention (e.g. RealWeatherDataProvider returns null on failure)
csharp
using System.Net.Http.Json;
using System.Text.Json.Serialization;

namespace AnimalAI.Plugins.Providers;

/// <summary>
/// Real [feature] data provider that uses [API/service].
/// </summary>
public class Real[Feature]DataProvider : I[Feature]DataProvider
{
    private static readonly HttpClient HttpClient = new();

    public async Task<ReturnType> MethodNameAsync(...)
    {
        try
        {
            // Call external API; map response to interface return type
            return ...;
        }
        catch
        {
            return null; // or default; match existing Real* style
        }
    }
}

Plugin Injection

In the plugin class under src/Plugins/Base/SK/:

  1. Add a field and constructor parameter for the provider; keep ILoggerFactory? as the first optional parameter.
  2. Default to the fake implementation when none is supplied.
csharp
#region Provider Fields
    private readonly I[Feature]DataProvider _dataProvider;
#endregion Provider Fields
#region Constructors
    public [Feature]Plugin(ILoggerFactory? loggerFactory = null, I[Feature]DataProvider? dataProvider = null)
    {
        _dataProvider = dataProvider ?? new Fake[Feature]DataProvider();
        _logger = loggerFactory?.CreateLogger<[Feature]Plugin>();
    }
#endregion Constructors

Use _dataProvider inside kernel functions instead of calling external APIs directly.

Conditional Fake vs Real (Config)

To choose fake vs real at runtime (e.g. in StandardKernel or a nested plugin), follow the Outlook pattern:

  1. Config: Add a constant or config key (e.g. in KernelConstants or appsettings), e.g. [Feature]ApiKey or [Feature]ServiceUrl.
  2. Wire-up: When constructing the plugin (or nested plugin), resolve the provider once:
csharp
// Uses Real[Feature]DataProvider if config is set, otherwise Fake for testing
I[Feature]DataProvider provider = string.IsNullOrEmpty(KernelConstants.[Feature]ConfigKey)
    ? new Fake[Feature]DataProvider()
    : new Real[Feature]DataProvider(KernelConstants.[Feature]ConfigKey);
var plugin = new [Feature]Plugin(loggerFactory, provider);
  1. KernelConstants: If the project uses KernelConstants, add something like:
csharp
/// <summary>
/// [Purpose]. Leave empty to use fake data for testing.
/// </summary>
public const string [Feature]ConfigKey = "";

Show this conditional pattern and, if applicable, the KernelConstants addition in the “how to inject” / “how to switch fake vs real” part of the answer.

Reference Implementations

  • Interface + small DTO: src/Plugins/Providers/Interfaces/IOutlookEmailProvider.cs
  • Interface only (no DTO): src/Plugins/Providers/Interfaces/IWeatherDataProvider.cs
  • Fake: src/Plugins/Providers/Fake/FakeWeatherDataProvider.cs, FakeOutlookEmailProvider.cs
  • Real: src/Plugins/Providers/Real/RealWeatherDataProvider.cs
  • Plugin using provider: src/Plugins/Base/SK/WeatherPlugin.cs, OutlookEmailPlugin.cs
  • Conditional wiring: src/AnimalKernel/Core/StandardKernel.cs (search for IOutlookEmailProvider / FakeOutlookEmailProvider)

Checklist Before Delivering

  • Interface and implementations use namespace AnimalAI.Plugins.Providers.
  • Only requested artifacts were created (Interface, Fake, Real, or both).
  • Plugin constructor uses ILoggerFactory? then I[Feature]DataProvider? and defaults provider to new Fake[Feature]DataProvider() when null.
  • If “conditional use” was requested, answer includes the conditional wiring snippet and any KernelConstants (or config) change.
  • Method names and return types match what the user asked for.