Forge
csharp1b5fd5de
1using System.Text.Json;
2
3namespace WebcamMcp.Shared;
4
5public static class ToolArgs
6{
7 public static string GetRequiredString(IReadOnlyDictionary<string, JsonElement> args, string key)
8 {
9 if (!args.TryGetValue(key, out var raw))
10 {
11 throw new ArgumentException($"{key} is required.");
12 }
13
14 var value = raw.GetString();
15 if (string.IsNullOrWhiteSpace(value))
16 {
17 throw new ArgumentException($"{key} is required.");
18 }
19
20 return value;
21 }
22
23 public static int GetOptionalInt(IReadOnlyDictionary<string, JsonElement> args, string key, int fallback)
24 {
25 if (!args.TryGetValue(key, out var raw))
26 {
27 return fallback;
28 }
29
30 return raw.ValueKind == JsonValueKind.Number && raw.TryGetInt32(out var value)
31 ? value
32 : fallback;
33 }
34
35 public static int? GetOptionalMonitorNumber(IReadOnlyDictionary<string, JsonElement> args, string key)
36 {
37 if (!args.TryGetValue(key, out var raw))
38 {
39 return null;
40 }
41
42 if (raw.ValueKind == JsonValueKind.Number && raw.TryGetInt32(out var numeric))
43 {
44 if (numeric == 0)
45 {
46 return null;
47 }
48
49 if (numeric > 0)
50 {
51 return numeric;
52 }
53
54 throw new ArgumentException($"{key} must be a positive monitor number or 'all'.");
55 }
56
57 if (raw.ValueKind == JsonValueKind.String)
58 {
59 var value = raw.GetString()?.Trim();
60 if (string.IsNullOrWhiteSpace(value) || string.Equals(value, "all", StringComparison.OrdinalIgnoreCase))
61 {
62 return null;
63 }
64
65 if (int.TryParse(value, out var parsed) && parsed > 0)
66 {
67 return parsed;
68 }
69
70 throw new ArgumentException($"{key} must be a positive monitor number or 'all'.");
71 }
72
73 throw new ArgumentException($"{key} must be a positive monitor number or 'all'.");
74 }
75
76 public static bool GetOptionalBool(IReadOnlyDictionary<string, JsonElement> args, string key, bool fallback)
77 {
78 if (!args.TryGetValue(key, out var raw))
79 {
80 return fallback;
81 }
82
83 return raw.ValueKind switch
84 {
85 JsonValueKind.True => true,
86 JsonValueKind.False => false,
87 _ => fallback
88 };
89 }
90
91 public static double GetOptionalDouble(IReadOnlyDictionary<string, JsonElement> args, string key, double fallback)
92 {
93 if (!args.TryGetValue(key, out var raw))
94 {
95 return fallback;
96 }
97
98 return raw.ValueKind == JsonValueKind.Number && raw.TryGetDouble(out var value)
99 ? value
100 : fallback;
101 }
102
103 public static string? GetOptionalString(IReadOnlyDictionary<string, JsonElement> args, string key)
104 {
105 if (!args.TryGetValue(key, out var raw))
106 {
107 return null;
108 }
109
110 return raw.ValueKind == JsonValueKind.String ? raw.GetString() : null;
111 }
112
113 public static string NormalizeImageFormat(string value)
114 {
115 var normalized = value.Trim().ToLowerInvariant();
116 return normalized switch
117 {
118 "jpeg" => "jpg",
119 "jpg" => "jpg",
120 "png" => "png",
121 _ => throw new ArgumentException("image_format must be 'jpg' or 'png'.")
122 };
123 }
124
125 public static string NormalizeVideoFormat(string value)
126 {
127 var normalized = value.Trim().ToLowerInvariant();
128 return normalized switch
129 {
130 "mp4" => "mp4",
131 "avi" => "avi",
132 _ => throw new ArgumentException("video_format must be 'mp4' or 'avi'.")
133 };
134 }
135
136 public static string MakeSafeFileName(string baseName)
137 {
138 var invalidChars = Path.GetInvalidFileNameChars();
139 var filtered = new string(baseName.Trim().Select(ch => invalidChars.Contains(ch) ? '_' : ch).ToArray());
140 return string.IsNullOrWhiteSpace(filtered) ? $"webcam-{DateTime.UtcNow:yyyyMMdd-HHmmss-fff}" : filtered;
141 }
142}
143
View only · write via MCP/CIDE