feat(worker): add DefaultAgentSeeder for first-launch agent seeding

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
mika kuns
2026-04-23 12:12:55 +02:00
parent e275f67a5e
commit 990be09bd7
2 changed files with 172 additions and 0 deletions

View File

@@ -0,0 +1,60 @@
using Microsoft.Extensions.Logging;
namespace ClaudeDo.Worker.Services;
public sealed record SeedResult(int Copied, int Skipped);
public sealed class DefaultAgentSeeder
{
private readonly string _bundleDir;
private readonly string _targetDir;
private readonly ILogger<DefaultAgentSeeder>? _logger;
public DefaultAgentSeeder(string bundleDir, string targetDir, ILogger<DefaultAgentSeeder>? logger = null)
{
_bundleDir = bundleDir;
_targetDir = targetDir;
_logger = logger;
}
public async Task<SeedResult> SeedMissingAsync(CancellationToken ct = default)
{
if (!Directory.Exists(_bundleDir))
{
_logger?.LogWarning("DefaultAgents bundle dir not found: {Dir}", _bundleDir);
return new SeedResult(0, 0);
}
Directory.CreateDirectory(_targetDir);
int copied = 0;
int skipped = 0;
foreach (var src in Directory.EnumerateFiles(_bundleDir, "*.md"))
{
ct.ThrowIfCancellationRequested();
var fileName = Path.GetFileName(src);
var dst = Path.Combine(_targetDir, fileName);
if (File.Exists(dst))
{
skipped++;
continue;
}
try
{
using var input = File.OpenRead(src);
using var output = File.Create(dst);
await input.CopyToAsync(output, ct);
copied++;
}
catch (Exception ex)
{
_logger?.LogWarning(ex, "Failed to copy default agent {File}", fileName);
}
}
return new SeedResult(copied, skipped);
}
}