| 1 | using AgentNotes.Core; |
| 2 | |
| 3 | namespace AgentNotesMcp.Status; |
| 4 | |
| 5 | internal static class AgentNotesStatusOnlyRunner |
| 6 | { |
| 7 | internal static async Task<int> RunAsync(string[] args) |
| 8 | { |
| 9 | var startupCode = AgentNotesBootstrap.TryLoadSettings(args, out var localSettings, out var startupError); |
| 10 | if (startupCode != 0) |
| 11 | { |
| 12 | Console.Error.WriteLine(startupError); |
| 13 | return startupCode; |
| 14 | } |
| 15 | |
| 16 | AgentNotesRuntime.Initialize(localSettings!, AgentNotesBootstrap.LoadedConfigPath); |
| 17 | |
| 18 | if (!localSettings!.Status.Enabled) |
| 19 | { |
| 20 | Console.Error.WriteLine("agent-notes-mcp --status-only requires [status].enabled = true in --config TOML."); |
| 21 | return AgentNotesBootstrap.ExitInvalidConfig; |
| 22 | } |
| 23 | |
| 24 | var storage = new NotesStorage(); |
| 25 | var startedAt = DateTimeOffset.UtcNow; |
| 26 | var (bindHost, bindWarning) = AgentNotesStatusBind.Resolve(localSettings.Status.Bind); |
| 27 | var plannedUrl = AgentNotesStatusBind.BuildBaseUrl(bindHost, localSettings.Status.Port); |
| 28 | var host = new AgentNotesStatusHost(storage, startedAt, plannedUrl, bindWarning); |
| 29 | |
| 30 | string? statusUrl; |
| 31 | string? error; |
| 32 | try |
| 33 | { |
| 34 | if (!host.TryStartForeground(out statusUrl, out error)) |
| 35 | { |
| 36 | Console.Error.WriteLine($"AgentNotesStatus: failed to start ({error})."); |
| 37 | return AgentNotesBootstrap.ExitInvalidConfig; |
| 38 | } |
| 39 | } |
| 40 | catch (Exception ex) |
| 41 | { |
| 42 | Console.Error.WriteLine($"AgentNotesStatus: failed to start ({ex.Message})."); |
| 43 | return AgentNotesBootstrap.ExitInvalidConfig; |
| 44 | } |
| 45 | |
| 46 | Console.Error.WriteLine($"AgentNotesStatus (--status-only): {statusUrl}"); |
| 47 | Console.Error.WriteLine("Press Ctrl+C to stop."); |
| 48 | |
| 49 | if (localSettings.Status.PreviewWorkspace is { } preview && statusUrl is not null) |
| 50 | AgentNotesStatusRuntimeFile.TryWrite(preview, statusUrl, AgentNotesBootstrap.LoadedConfigPath ?? ""); |
| 51 | |
| 52 | using var cts = new CancellationTokenSource(); |
| 53 | Console.CancelKeyPress += (_, e) => |
| 54 | { |
| 55 | e.Cancel = true; |
| 56 | cts.Cancel(); |
| 57 | }; |
| 58 | |
| 59 | try |
| 60 | { |
| 61 | await Task.Delay(Timeout.Infinite, cts.Token).ConfigureAwait(false); |
| 62 | } |
| 63 | catch (OperationCanceledException) |
| 64 | { |
| 65 | // shutdown |
| 66 | } |
| 67 | finally |
| 68 | { |
| 69 | await host.StopAsync().ConfigureAwait(false); |
| 70 | } |
| 71 | |
| 72 | return 0; |
| 73 | } |
| 74 | } |
| 75 | |