feat(daily-prep): add set_my_day MCP tool with cap-guard
This commit is contained in:
@@ -30,7 +30,9 @@ public sealed record TaskDto(
|
||||
string? CreatedBy,
|
||||
DateTime CreatedAt,
|
||||
DateTime? StartedAt,
|
||||
DateTime? FinishedAt);
|
||||
DateTime? FinishedAt,
|
||||
bool IsMyDay,
|
||||
int SortOrder);
|
||||
|
||||
public sealed record WorktreeInfoDto(
|
||||
string Path, string Branch, string HeadCommit, string BaseCommit,
|
||||
@@ -529,6 +531,41 @@ public sealed class ExternalMcpService
|
||||
return new DailyPrepDataDto(maxTasks, candidates, currentMyDay);
|
||||
}
|
||||
|
||||
[McpServerTool, Description(
|
||||
"Daily prep: set or clear a task's MyDay flag, optionally setting its sortOrder " +
|
||||
"(use consecutive sortOrder values to keep related tasks together). " +
|
||||
"Setting isMyDay=true is rejected if it would exceed the MyDay cap (DailyPrepMaxTasks open MyDay tasks); " +
|
||||
"clearing (isMyDay=false) is always allowed.")]
|
||||
public async Task<TaskDto> SetMyDay(
|
||||
string taskId,
|
||||
bool isMyDay,
|
||||
int? sortOrder,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
await using var ctx = await _dbFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
var task = await ctx.Tasks.FirstOrDefaultAsync(t => t.Id == taskId, cancellationToken)
|
||||
?? throw new InvalidOperationException($"Task {taskId} not found.");
|
||||
|
||||
if (isMyDay && !task.IsMyDay)
|
||||
{
|
||||
var settings = await new AppSettingsRepository(ctx).GetAsync(cancellationToken);
|
||||
var max = settings.DailyPrepMaxTasks < 1 ? 1 : settings.DailyPrepMaxTasks;
|
||||
var openMyDay = await ctx.Tasks.CountAsync(
|
||||
t => t.IsMyDay && t.Status == TaskStatus.Idle, cancellationToken);
|
||||
if (openMyDay >= max)
|
||||
throw new InvalidOperationException(
|
||||
$"MyDay limit {max} reached. Clear a task before adding another.");
|
||||
}
|
||||
|
||||
task.IsMyDay = isMyDay;
|
||||
if (sortOrder is not null) task.SortOrder = sortOrder.Value;
|
||||
await ctx.SaveChangesAsync(cancellationToken);
|
||||
|
||||
await _broadcaster.TaskUpdated(taskId);
|
||||
return ToDto(task);
|
||||
}
|
||||
|
||||
private static DailyPrepCandidateDto ToCandidate(TaskEntity t) => new(
|
||||
t.Id, t.ListId, t.List?.Name ?? "", t.Title, t.Description,
|
||||
t.IsStarred, t.ScheduledFor, t.CreatedAt);
|
||||
@@ -618,7 +655,9 @@ public sealed class ExternalMcpService
|
||||
t.CreatedBy,
|
||||
t.CreatedAt,
|
||||
t.StartedAt,
|
||||
t.FinishedAt);
|
||||
t.FinishedAt,
|
||||
t.IsMyDay,
|
||||
t.SortOrder);
|
||||
}
|
||||
|
||||
internal static class DailyPrepFilter
|
||||
|
||||
Reference in New Issue
Block a user