| 1 | using System.Text.Json; |
| 2 | using CascadeIDE.Features.AutonomousAgent; |
| 3 | using CascadeIDE.Features.UiChrome; |
| 4 | using CommunityToolkit.Mvvm.Input; |
| 5 | |
| 6 | namespace CascadeIDE.ViewModels; |
| 7 | |
| 8 | /// <summary>Автономный агент (Power).</summary> |
| 9 | public partial class MainWindowViewModel |
| 10 | { |
| 11 | UiModeFamily IAutonomousAgentSessionHost.UiModeFamily => UiModeFamily; |
| 12 | |
| 13 | string IAutonomousAgentSessionHost.SafetyLevel |
| 14 | { |
| 15 | get => SafetyLevel; |
| 16 | set => SafetyLevel = value; |
| 17 | } |
| 18 | |
| 19 | string IAutonomousAgentSessionHost.ResultSummary |
| 20 | { |
| 21 | get => ResultSummary; |
| 22 | set => ResultSummary = value; |
| 23 | } |
| 24 | |
| 25 | void IAutonomousAgentSessionHost.SetActiveTaskStrip(string title, string status, int progress) |
| 26 | { |
| 27 | ActiveTaskTitle = title; |
| 28 | ActiveTaskStatus = status; |
| 29 | ActiveTaskProgress = progress; |
| 30 | } |
| 31 | |
| 32 | void IAutonomousAgentSessionHost.OpenChatForAgentFallback(string chatInput) |
| 33 | { |
| 34 | ApplyMfdRegionExpanded(true); |
| 35 | ChatPanel.ChatInput = chatInput; |
| 36 | } |
| 37 | |
| 38 | [RelayCommand] |
| 39 | private void ExplainCurrentStep() |
| 40 | { |
| 41 | ApplyMfdRegionExpanded(true); |
| 42 | ChatPanel.ChatInput = "Explain the current autonomous step in plain language: intent, tool call, risk, and rollback."; |
| 43 | } |
| 44 | |
| 45 | [RelayCommand] |
| 46 | private void ExplainTraceStep(AgentTraceStepViewModel? step) |
| 47 | { |
| 48 | if (step is null) |
| 49 | return; |
| 50 | ApplyMfdRegionExpanded(true); |
| 51 | ChatPanel.ChatInput = |
| 52 | $"Объясни шаг трассы [{step.Kind} / {step.Status}] ({step.TimestampText}): {step.Text}. Укажи намерение, риск и откат."; |
| 53 | } |
| 54 | |
| 55 | [RelayCommand] |
| 56 | private void RollbackTraceStep(AgentTraceStepViewModel? step) |
| 57 | { |
| 58 | if (step is null) |
| 59 | return; |
| 60 | InstrumentationPanel.EventTimeline.Insert(0, $"{DateTime.Now:HH:mm:ss} — Запрошен откат для шага [{step.Kind}]"); |
| 61 | ApplyMfdRegionExpanded(true); |
| 62 | ChatPanel.ChatInput = |
| 63 | $"Предложи минимальный откат для шага [{step.Kind}] ({step.TimestampText}): {step.Text}. Проверь состояние workspace."; |
| 64 | } |
| 65 | |
| 66 | /// <summary>Добавить шаг в Agent Trace Timeline (Power); потокобезопасно.</summary> |
| 67 | public void AppendAgentTraceStep(string kind, string text, string status, DateTimeOffset? at = null) => |
| 68 | InstrumentationPanel.AppendAgentTraceStep(kind, text, status, at); |
| 69 | |
| 70 | private void RefreshWorkspaceSnapshotCore() |
| 71 | { |
| 72 | try |
| 73 | { |
| 74 | var json = GetUiLayoutProvider?.Invoke() ?? "{}"; |
| 75 | if (json.Length > 4000) |
| 76 | json = json[..4000] + "\n…"; |
| 77 | WorkspaceSnapshotJson = json; |
| 78 | } |
| 79 | catch (Exception ex) |
| 80 | { |
| 81 | WorkspaceSnapshotJson = JsonSerializer.Serialize(new { error = ex.Message }); |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | [RelayCommand] |
| 86 | private void RefreshWorkspaceSnapshot() => RefreshWorkspaceSnapshotCore(); |
| 87 | |
| 88 | [RelayCommand] |
| 89 | private void EmergencyStop() |
| 90 | { |
| 91 | IsBuilding = false; |
| 92 | Autonomous.CancelAutonomousRunCompletely(); |
| 93 | InstrumentationPanel.EventTimeline.Insert(0, $"{DateTime.Now:HH:mm:ss} — Emergency stop engaged"); |
| 94 | } |
| 95 | |
| 96 | /// <summary>Focus: зафиксировать контрольную точку в таймлайне и кратком результате.</summary> |
| 97 | [RelayCommand] |
| 98 | private void FocusCheckpoint() |
| 99 | { |
| 100 | var stamp = DateTime.Now; |
| 101 | InstrumentationPanel.EventTimeline.Insert(0, $"{stamp:HH:mm:ss} — Контрольная точка"); |
| 102 | ResultSummary = $"Контрольная точка: {stamp:yyyy-MM-dd HH:mm}"; |
| 103 | } |
| 104 | |
| 105 | /// <summary>Focus: запрос на откат — подсказка в чат и событие в таймлайне.</summary> |
| 106 | [RelayCommand] |
| 107 | private void FocusRollback() |
| 108 | { |
| 109 | InstrumentationPanel.EventTimeline.Insert(0, $"{DateTime.Now:HH:mm:ss} — Запрошен откат"); |
| 110 | ApplyMfdRegionExpanded(true); |
| 111 | ChatPanel.ChatInput = "Помоги безопасно откатить последние изменения (git или патчи). Оцени риск и предложи минимальный набор команд."; |
| 112 | } |
| 113 | |
| 114 | /// <summary>Focus: подтвердить текущий шаг в гейте.</summary> |
| 115 | [RelayCommand] |
| 116 | private void ConfirmFocusStep() |
| 117 | { |
| 118 | InstrumentationPanel.EventTimeline.Insert(0, $"{DateTime.Now:HH:mm:ss} — Шаг подтверждён"); |
| 119 | ActiveTaskStatus = "В работе"; |
| 120 | } |
| 121 | |
| 122 | /// <summary>Focus: отменить предложенный шаг.</summary> |
| 123 | [RelayCommand] |
| 124 | private void CancelFocusStep() |
| 125 | { |
| 126 | InstrumentationPanel.EventTimeline.Insert(0, $"{DateTime.Now:HH:mm:ss} — Шаг отменён"); |
| 127 | NextActionSummary = "Ожидание следующего шага."; |
| 128 | ActiveTaskStatus = "Ожидание"; |
| 129 | } |
| 130 | } |
| 131 | |