feat: add backend plan mode checkpoints

Add backend support for plan-mode turn shaping and exit-plan review
checkpoints. Run-turn commands now accept an interaction mode,
plan-mode prompt guidance tells agents to produce a plan and call
exit_plan_mode, and the sidecar emits a structured
exit-plan-mode-requested event when the SDK raises that session event.

For now the backend intentionally treats exit_plan_mode as a turn
boundary and graceful-degradation review checkpoint. The current
Agent Framework GitHubCopilotAgent wrapper does not expose a clean way
to bridge the live CopilotSession back into same-turn exit-plan
resolution, so that follow-up remains documented for the frontend and a
future backend slice.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
David Kaya
2026-03-26 23:29:32 +01:00
co-authored by Copilot
parent c069b86add
commit 380e402512
11 changed files with 422 additions and 54 deletions
@@ -161,6 +161,7 @@ public sealed class RunTurnCommandDto : SidecarCommandEnvelope
public string SessionId { get; init; } = string.Empty;
public string ProjectPath { get; init; } = string.Empty;
public string WorkspaceKind { get; init; } = "project";
public string Mode { get; init; } = "interactive";
public PatternDefinitionDto Pattern { get; init; } = new();
public IReadOnlyList<ChatMessageDto> Messages { get; init; } = [];
public RunTurnToolingConfigDto? Tooling { get; init; }
@@ -308,6 +309,18 @@ public sealed class UserInputRequestedEventDto : SidecarEventDto
public bool? AllowFreeform { get; init; }
}
public sealed class ExitPlanModeRequestedEventDto : SidecarEventDto
{
public string SessionId { get; init; } = string.Empty;
public string ExitPlanId { get; init; } = string.Empty;
public string? AgentId { get; init; }
public string? AgentName { get; init; }
public string Summary { get; init; } = string.Empty;
public string PlanContent { get; init; } = string.Empty;
public IReadOnlyList<string>? Actions { get; init; }
public string? RecommendedAction { get; init; }
}
public sealed class CommandErrorEventDto : SidecarEventDto
{
public string Message { get; init; } = string.Empty;