Files
EugeneTes 28bbfbc759 feat(scheduler): store jobs per chat and import VolcanicSecretary job files
Each chat's jobs live in <workspace>/.volcanic/scheduler/jobs.json. On start the
scheduler loads every chat's file, moves the retired shared
<agentDir>/scheduler/jobs.json into them and renames it .migrated-<ts>.
A VolcanicSecretary jobs.json (bare array) in a chat's folder is converted
in place for that chat; the original is kept as .secretary-<ts>.

Also adds the VolcanicSecretary data migration plan.
2026-10-02 07:29:48 +00:00

39 lines
2.0 KiB
C#

namespace Volcanic.AgenticCore.Extensions.Scheduler;
/// <summary>The <c>Scheduler</c> configuration section. There is no zone here: zones are per target (the host's <c>IJobDelivery.TimeZoneFor</c>).</summary>
public sealed class SchedulerOptions
{
public const string SectionName = "Scheduler";
public bool Enabled { get; set; } = true;
/// <summary>
/// The retired shared <c>jobs.json</c>. Jobs are kept per chat (<see cref="JobStore.PathIn"/>); on start the jobs
/// found here move into their chats' files and this file is renamed <c>jobs.json.migrated-&lt;timestamp&gt;</c>.
/// Empty: the host fills <see cref="DefaultLegacyStorePath"/> under its agent directory.
/// </summary>
public string? LegacyStorePath { get; set; }
/// <summary>Watcher timeout when the job sets none.</summary>
public TimeSpan DefaultScriptTimeout { get; set; } = TimeSpan.FromSeconds(300);
public int MaxJobsPerTarget { get; set; } = 50;
/// <summary>Executable and leading arguments; the command is appended. Empty: <c>/bin/sh -c</c>, or <c>cmd.exe /d /s /c</c> on Windows (the <c>bash</c> tool's shell).</summary>
public List<string> Shell { get; set; } = [];
/// <summary><c>&lt;agentDir&gt;/scheduler/jobs.json</c>.</summary>
public static string DefaultLegacyStorePath(string agentDir) => Path.Combine(agentDir, "scheduler", "jobs.json");
/// <summary>Configuration problems that must stop the host, empty when valid.</summary>
public IReadOnlyList<string> Validate()
{
var errors = new List<string>();
if (DefaultScriptTimeout < TimeSpan.FromSeconds(1) || DefaultScriptTimeout > TimeSpan.FromSeconds(JobValidation.MaxTimeoutSeconds))
errors.Add("Scheduler:DefaultScriptTimeout must be between 1 second and 1 hour.");
if (MaxJobsPerTarget < 1) errors.Add("Scheduler:MaxJobsPerTarget must be at least 1.");
if (Shell.Any(string.IsNullOrWhiteSpace)) errors.Add("Scheduler:Shell entries must not be empty.");
return errors;
}
}