Forge
deeb25a2
1#!/usr/bin/env dotnet script
2// Запуск (из каталога cascade-ide или с путём к скрипту):
3// dotnet script docs/samples/agent-contract-ci.csx -- --exe path\to\CascadeIDE.exe
4// dotnet script docs/samples/agent-contract-ci.csx -- --exe path\to\CascadeIDE.exe --workspace D:\repo
5// Один раз: dotnet tool install -g dotnet-script (как в Financial/finplan, agents-and-humans-book).
6
7using System.Diagnostics;
8using System.Text;
9using System.Text.Json;
10
11static string[] GetArgsAfterCsx()
12{
13 var a = Environment.GetCommandLineArgs();
14 for (var i = 0; i < a.Length; i++)
15 {
16 if (!a[i].EndsWith(".csx", StringComparison.OrdinalIgnoreCase) || i + 1 >= a.Length)
17 continue;
18 var tail = a.AsSpan(i + 1).ToArray();
19 // dotnet script foo.csx -- --exe … → после .csx часто идёт разделитель "--"
20 if (tail.Length > 0 && tail[0] == "--")
21 return tail.AsSpan(1).ToArray();
22 return tail;
23 }
24 return Array.Empty<string>();
25}
26
27static int RunAgentContract(string exe, string[] arguments, out string stdout, out string stderr)
28{
29 stdout = "";
30 stderr = "";
31 var psi = new ProcessStartInfo(exe)
32 {
33 UseShellExecute = false,
34 RedirectStandardOutput = true,
35 RedirectStandardError = true,
36 CreateNoWindow = true,
37 };
38 foreach (var arg in arguments)
39 psi.ArgumentList.Add(arg);
40 using var p = Process.Start(psi);
41 if (p is null)
42 return -1;
43 stdout = p.StandardOutput.ReadToEnd();
44 stderr = p.StandardError.ReadToEnd();
45 p.WaitForExit();
46 return p.ExitCode;
47}
48
49var tail = GetArgsAfterCsx();
50string cascadeExe = null;
51var workspace = Environment.CurrentDirectory;
52for (var i = 0; i < tail.Length; i++)
53{
54 if (string.Equals(tail[i], "--exe", StringComparison.OrdinalIgnoreCase))
55 {
56 if (i + 1 >= tail.Length) { Console.Error.WriteLine("--exe requires a path."); Environment.Exit(2); }
57 cascadeExe = tail[++i];
58 continue;
59 }
60 if (string.Equals(tail[i], "--workspace", StringComparison.OrdinalIgnoreCase))
61 {
62 if (i + 1 >= tail.Length) { Console.Error.WriteLine("--workspace requires a path."); Environment.Exit(2); }
63 workspace = tail[++i];
64 continue;
65 }
66 Console.Error.WriteLine($"Unknown argument: {tail[i]}");
67 Environment.Exit(2);
68}
69
70if (string.IsNullOrWhiteSpace(cascadeExe) || !File.Exists(cascadeExe))
71{
72 Console.Error.WriteLine("Usage: dotnet script agent-contract-ci.csx -- --exe <path\\to\\CascadeIDE.exe> [--workspace <repoRoot>]");
73 Console.Error.WriteLine("Requires a built/published CascadeIDE.exe.");
74 Environment.Exit(2);
75}
76
77string json;
78int code;
79
80code = RunAgentContract(cascadeExe, ["--agent-contract", "get_ui_modes_diagnostics"], out json, out var err);
81if (code != 0) { Console.Error.WriteLine(err); Environment.Exit(code); }
82if (string.IsNullOrWhiteSpace(json)) { Console.Error.WriteLine("empty stdout from get_ui_modes_diagnostics"); Environment.Exit(3); }
83
84code = RunAgentContract(cascadeExe, ["--agent-contract", "get_supported_editor_languages"], out json, out err);
85if (code != 0) { Console.Error.WriteLine(err); Environment.Exit(code); }
86
87code = RunAgentContract(cascadeExe, ["--agent-contract", "get_solution_info"], out json, out err);
88if (code != 0) { Console.Error.WriteLine(err); Environment.Exit(code); }
89try { JsonDocument.Parse(json); }
90catch (Exception ex) { Console.Error.WriteLine($"get_solution_info: invalid JSON: {ex.Message}"); Environment.Exit(3); }
91
92code = RunAgentContract(cascadeExe, ["--agent-contract", "get_cockpit_surface"], out json, out err);
93if (code != 0) { Console.Error.WriteLine(err); Environment.Exit(code); }
94try { JsonDocument.Parse(json); }
95catch (Exception ex) { Console.Error.WriteLine($"get_cockpit_surface: invalid JSON: {ex.Message}"); Environment.Exit(3); }
96
97code = RunAgentContract(cascadeExe, ["--agent-contract", "get_ide_state"], out json, out err);
98if (code != 0) { Console.Error.WriteLine(err); Environment.Exit(code); }
99try
100{
101 using var doc = JsonDocument.Parse(json);
102 if (!doc.RootElement.TryGetProperty("cockpit_surface", out _))
103 {
104 Console.Error.WriteLine("get_ide_state: missing cockpit_surface");
105 Environment.Exit(3);
106 }
107}
108catch (Exception ex) { Console.Error.WriteLine($"get_ide_state: invalid JSON: {ex.Message}"); Environment.Exit(3); }
109
110code = RunAgentContract(cascadeExe, ["--agent-contract", "--workspace", workspace, "git_status"], out json, out err);
111if (code != 0) { Console.Error.WriteLine(err); Environment.Exit(code); }
112
113Console.WriteLine("OK: agent-contract checks passed (ui_modes, languages, solution_info, cockpit, ide_state, git_status).");
114Environment.Exit(0);
115
View only · write via MCP/CIDE