RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/Cursor rules/SethRobinson/UGTLive

Cursor rule

.cursor/rules/service-integration-patterns.mdc

Patterns for integrating external services (APIs, OCR, TTS)

Cursor rules

Quality

69/100

Scores the file, not the repository.

Length

1,236 words

41 headings · 25 code blocks

Repository

103

— · pushed 17 days ago

Last changed

3 days ago

First indexed 3 days ago.
SethRobinson/UGTLive/.cursor/rules/service-integration-patterns.mdcRawGitHub
1---
2description: Patterns for integrating external services (APIs, OCR, TTS)
3globs: ["**/*Service.cs", "**/*Manager.cs"]
4alwaysApply: false
5---
6 
7# Service Integration Patterns
8 
9## Translation Service Interface
10 
11### ITranslationService Pattern
12All translation services implement a common interface:
13 
14```csharp
15public interface ITranslationService
16{
17 Task<TranslationResult?> TranslateAsync(
18 string sourceText,
19 string targetLanguage,
20 string context);
21}
22```
23 
24### TranslationResult Structure
25```csharp
26public class TranslationResult
27{
28 public string TranslatedText { get; set; } = "";
29 public string SourceLanguage { get; set; } = "";
30 public double Confidence { get; set; } = 1.0;
31}
32```
33 
34## HTTP Client Usage
35 
36### Service HTTP Client Pattern
37Each service creates its own HttpClient:
38 
39```csharp
40public class GeminiTranslationService : ITranslationService
41{
42 private static readonly HttpClient _httpClient = new HttpClient();
43 private readonly string _apiKey;
44
45 public GeminiTranslationService()
46 {
47 _apiKey = ConfigManager.Instance.GetGeminiApiKey();
48 }
49
50 public async Task<TranslationResult?> TranslateAsync(string text, string lang, string context)
51 {
52 // Implementation
53 }
54}
55```
56 
57### Request Building
58```csharp
59var requestBody = new
60{
61 contents = new[]
62 {
63 new
64 {
65 parts = new[]
66 {
67 new { text = prompt }
68 }
69 }
70 }
71};
72 
73var json = JsonSerializer.Serialize(requestBody);
74var content = new StringContent(json, Encoding.UTF8, "application/json");
75var response = await _httpClient.PostAsync(url, content);
76```
77 
78## Error Handling in Services
79 
80### HTTP Error Handling Pattern
81```csharp
82if (response.IsSuccessStatusCode)
83{
84 var result = await response.Content.ReadAsStringAsync();
85 return ParseResult(result);
86}
87else
88{
89 string errorMessage = await response.Content.ReadAsStringAsync();
90 Console.WriteLine($"API error: {response.StatusCode}, {errorMessage}");
91
92 // Try to parse JSON error
93 try
94 {
95 using JsonDocument errorDoc = JsonDocument.Parse(errorMessage);
96 if (errorDoc.RootElement.TryGetProperty("error", out JsonElement errorElement))
97 {
98 // Extract detailed error
99 return null;
100 }
101 }
102 catch (JsonException)
103 {
104 // Fallback to raw message
105 }
106
107 // Show user-friendly error
108 ErrorPopupManager.ShowError("Translation Error", errorMessage);
109
110 return null;
111}
112```
113 
114### Exception Handling
115```csharp
116try
117{
118 var response = await _httpClient.PostAsync(url, content);
119 // Process response
120}
121catch (Exception ex)
122{
123 Console.WriteLine($"Service error: {ex.Message}");
124 LogManager.Instance.LogError("Translation failed", ex);
125
126 ErrorPopupManager.ShowError("Translation Error", ex.Message);
127
128 return null;
129}
130```
131 
132## Service Factory Pattern
133 
134### TranslationServiceFactory
135```csharp
136public static class TranslationServiceFactory
137{
138 public static ITranslationService CreateService(string serviceName)
139 {
140 return serviceName switch
141 {
142 "Gemini" => new GeminiTranslationService(),
143 "ChatGPT" => new ChatGptTranslationService(),
144 "Ollama" => new OllamaTranslationService(),
145 "Google Translate" => new GoogleTranslateService(),
146 "llama.cpp" => new LlamaCppTranslationService(),
147 _ => throw new ArgumentException($"Unknown service: {serviceName}")
148 };
149 }
150}
151```
152 
153## OCR Service Integration
154 
155### Windows OCR Pattern
156```csharp
157public class WindowsOCRManager
158{
159 public async Task<List<TextObject>> ProcessImageAsync(Bitmap bitmap)
160 {
161 return await Task.Run(() =>
162 {
163 // Convert bitmap to Windows bitmap
164 // Process with Windows OCR API
165 // Return TextObject list
166 });
167 }
168}
169```
170 
171### Google Vision OCR Pattern
172```csharp
173public class GoogleVisionOCRService
174{
175 public async Task<List<TextObject>> ProcessImageAsync(Bitmap bitmap)
176 {
177 // Convert bitmap to base64
178 // Send to Google Vision API
179 // Parse response and return TextObject list
180 }
181}
182```
183 
184### Python OCR Service Pattern (HTTP-based)
185```csharp
186// Services are managed via PythonServicesManager
187// Discover services on startup
188PythonServicesManager.Instance.DiscoverServices();
189 
190// Get service by name
191var service = PythonServicesManager.Instance.GetServiceByName("EasyOCR");
192 
193// Check if service is running
194if (!service.IsRunning)
195{
196 bool isRunning = await service.CheckIsRunningAsync();
197 if (!isRunning)
198 {
199 // Show error dialog or start service
200 await service.StartAsync(showWindow: false);
201 }
202}
203 
204// Process image with HTTP service
205private async Task<string?> ProcessImageWithHttpServiceAsync(byte[] imageBytes, string serviceName, string language)
206{
207 var service = PythonServicesManager.Instance.GetServiceByName(serviceName);
208 if (service == null) return null;
209
210 // Build URL with query parameters
211 string langParam = MapLanguageForService(language);
212 string url = $"{service.ServerUrl}:{service.Port}/process?lang={langParam}&char_level=true";
213
214 // Add service-specific parameters (e.g., MangaOCR)
215 if (serviceName == "MangaOCR")
216 {
217 url += $"&min_region_width={minWidth}&min_region_height={minHeight}&overlap_allowed_percent={overlapPercent}";
218 }
219
220 // Add PaddleOCR-specific parameters
221 if (serviceName == "PaddleOCR")
222 {
223 bool useAngleCls = ConfigManager.Instance.GetBoolValue(ConfigManager.PADDLE_OCR_USE_ANGLE_CLS, false);
224 url += $"&use_angle_cls={useAngleCls.ToString().ToLower()}";
225 }
226
227 // Send binary image data
228 var content = new ByteArrayContent(imageBytes);
229 content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
230
231 using var request = new HttpRequestMessage(HttpMethod.Post, url);
232 request.Content = content;
233 request.Headers.ConnectionClose = false; // Enable HTTP keep-alive
234 var response = await _httpClient.SendAsync(request);
235
236 if (!response.IsSuccessStatusCode)
237 {
238 service.MarkAsNotRunning();
239 return null;
240 }
241
242 return await response.Content.ReadAsStringAsync();
243}
244```
245 
246## Text-to-Speech Integration
247 
248### TTS Service Pattern
249```csharp
250public interface ITTSService
251{
252 Task<byte[]?> SynthesizeAsync(string text, string language);
253}
254 
255public class GoogleTTSService : ITTSService
256{
257 public async Task<byte[]?> SynthesizeAsync(string text, string language)
258 {
259 var url = $"https://texttospeech.googleapis.com/v1/text:synthesize";
260 // Build request and get audio bytes
261 return audioBytes;
262 }
263}
264```
265 
266## Audio Processing
267 
268### NAudio Integration
269```csharp
270using NAudio.Wave;
271 
272public class AudioPlaybackManager
273{
274 private WaveOutEvent? _waveOut;
275
276 public void PlayAudio(byte[] audioData)
277 {
278 _waveOut?.Stop();
279 _waveOut?.Dispose();
280
281 using var ms = new MemoryStream(audioData);
282 using var reader = new Mp3FileReader(ms);
283
284 _waveOut = new WaveOutEvent();
285 _waveOut.Init(reader);
286 _waveOut.Play();
287 }
288}
289```
290 
291### Audio Preloading
292```csharp
293public class AudioPreloadService
294{
295 // Preload audio for source and target languages
296 public async Task PreloadAudioAsync(string text, string language, string service)
297 {
298 // Generate audio and cache it
299 // Used for faster playback later
300 }
301}
302```
303 
304## Real-time Audio Streaming
305 
306### WebSocket Pattern
307```csharp
308public class OpenAIRealtimeAudioService
309{
310 private ClientWebSocket? _webSocket;
311
312 public async Task ConnectAsync()
313 {
314 _webSocket = new ClientWebSocket();
315 await _webSocket.ConnectAsync(new Uri("wss://api.openai.com/v1/realtime"), CancellationToken.None);
316
317 // Start receiving loop
318 _ = Task.Run(ReceiveLoop);
319 }
320
321 private async Task ReceiveLoop()
322 {
323 var buffer = new byte[4096];
324 while (_webSocket?.State == WebSocketState.Open)
325 {
326 var result = await _webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
327 ProcessMessage(buffer, result.Count);
328 }
329 }
330}
331```
332 
333## Service Configuration
334 
335### Python OCR Service Configuration
336Python OCR services are configured via `service_config.txt` files in each service directory:
337 
338```csharp
339// Service discovery reads service_config.txt
340// Format: key|value|
341// Fields: service_name, venv_name, port, description, version, author, github_url, local_only, server_url
342 
343// C# PythonService.ParseFromConfig() reads the config file
344var service = PythonService.ParseFromConfig(serviceDirectory);
345 
346// Service properties available:
347// - service.ServiceName (from service_name)
348// - service.VenvName (from venv_name)
349// - service.Port (from port)
350// - service.Description, Version, Author, GithubUrl, etc.
351```
352 
353### Translation Service Configuration
354Translation services read their configuration from ConfigManager:
355 
356```csharp
357public class GeminiTranslationService
358{
359 private readonly string _apiKey;
360 private readonly string _model;
361 private readonly string _prompt;
362
363 public GeminiTranslationService()
364 {
365 _apiKey = ConfigManager.Instance.GetGeminiApiKey();
366 _model = ConfigManager.Instance.GetGeminiModel();
367 _prompt = ConfigManager.Instance.GetGeminiPrompt();
368 }
369}
370```
371 
372## Retry Logic
373 
374### Exponential Backoff Pattern
375```csharp
376public async Task<TranslationResult?> TranslateWithRetryAsync(string text, int maxRetries = 3)
377{
378 for (int attempt = 0; attempt < maxRetries; attempt++)
379 {
380 try
381 {
382 return await TranslateAsync(text);
383 }
384 catch (Exception ex)
385 {
386 if (attempt == maxRetries - 1)
387 {
388 throw;
389 }
390
391 int delay = (int)Math.Pow(2, attempt) * 1000; // Exponential backoff
392 await Task.Delay(delay);
393 }
394 }
395
396 return null;
397}
398```
399 
400## Timeout Handling
401 
402### Request Timeout
403```csharp
404private static readonly HttpClient _httpClient = new HttpClient
405{
406 Timeout = TimeSpan.FromSeconds(30)
407};
408```
409 
410### Cancellation Token
411```csharp
412using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
413var response = await _httpClient.PostAsync(url, content, cts.Token);
414```
415 
416## JSON Serialization
417 
418### System.Text.Json Pattern
419```csharp
420using System.Text.Json;
421 
422var options = new JsonSerializerOptions
423{
424 PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
425 WriteIndented = false
426};
427 
428var json = JsonSerializer.Serialize(requestObject, options);
429var responseObject = JsonSerializer.Deserialize<ResponseType>(jsonString, options);
430```
431 
432## Service Health Checks
433 
434### Connection Testing
435```csharp
436public async Task<bool> TestConnectionAsync()
437{
438 try
439 {
440 var testRequest = new { text = "test" };
441 var result = await TranslateAsync("test", "en", "");
442 return result != null;
443 }
444 catch
445 {
446 return false;
447 }
448}
449```
450 
451### Python Service Health Check
452```csharp
453public async Task<bool> CheckServiceHealthAsync(PythonService service)
454{
455 try
456 {
457 var url = $"{service.ServerUrl}:{service.Port}/health";
458 var response = await _httpClient.GetAsync(url);
459 return response.IsSuccessStatusCode;
460 }
461 catch
462 {
463 return false;
464 }
465}
466```
467 
468## Service Discovery
469 
470### Python Service Discovery
471```csharp
472// Automatically discovers services in app/services/
473PythonServicesManager.Instance.DiscoverServices();
474 
475// Get all discovered services
476var services = PythonServicesManager.Instance.GetAllServices();
477 
478// Get service by name
479var easyOCR = PythonServicesManager.Instance.GetServiceByName("EasyOCR");
480```
481 
482## Service Lifecycle Management
483 
484### Starting Services
485```csharp
486public async Task<bool> StartServiceAsync(PythonService service, bool showWindow = false)
487{
488 if (service.IsRunning)
489 {
490 return true;
491 }
492
493 // Start Python server process
494 // Wait for health check
495 // Mark as running
496}
497```
498 
499### Stopping Services
500```csharp
501public async Task StopServiceAsync(PythonService service)
502{
503 if (!service.IsRunning)
504 {
505 return;
506 }
507
508 // Send shutdown request
509 // Wait for process to exit
510 // Mark as not running
511}
512```
513 

Sections

  • Service Integration Patterns
  • Translation Service Interface
  • ITranslationService Pattern
  • TranslationResult Structure
  • HTTP Client Usage
  • Service HTTP Client Pattern
  • Request Building
  • Error Handling in Services
  • HTTP Error Handling Pattern
  • Exception Handling
  • Service Factory Pattern
  • TranslationServiceFactory
  • OCR Service Integration
  • Windows OCR Pattern
  • Google Vision OCR Pattern
  • Python OCR Service Pattern (HTTP-based)
  • Text-to-Speech Integration
  • TTS Service Pattern
  • Audio Processing
  • NAudio Integration
  • Audio Preloading
  • Real-time Audio Streaming
  • WebSocket Pattern
  • Service Configuration
  • Python OCR Service Configuration
  • Translation Service Configuration
  • Retry Logic
  • Exponential Backoff Pattern
  • Timeout Handling
  • Request Timeout
  • Cancellation Token
  • JSON Serialization
  • System.Text.Json Pattern
  • Service Health Checks
  • Connection Testing
  • Python Service Health Check
  • Service Discovery
  • Python Service Discovery
  • Service Lifecycle Management
  • Starting Services
  • Stopping Services

What it covers

buildtestcode-stylearchitecture

Stack — with the evidence

csharp

(1.00)

ai-agent

(0.90)

dotnet

(0.60)

github-actions

(0.60)

Glob targeting

  • **/*Service.cs
  • **/*Manager.cs

Format

Cursor rules

The most expressive format here. Many small .mdc files, each with frontmatter declaring when it should load, so a rule about migrations only enters context when a migration is open. Costs the most to maintain and only one editor reads it.

What the corpus says about it

Repository

Owner
SethRobinson
Language
—
License
—
Archived
no

All configs in this repo

Also in SethRobinson/UGTLive

Diff this repo’s formats

One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?

The other instruction files in this repository
RepositoryFormatStackCoversScoreChanged
SethRobinson/UGTLive.cursor/rules/ui-ux-patterns.mdc · 103Cursor rulescsharpai-agent+2stylearchtypesui+162/1003 days ago
SethRobinson/UGTLive.cursor/rules/architecture-patterns.mdc · 103Cursor rulescsharpai-agent+2buildtestlint-formatstyle+677/1003 days ago
SethRobinson/UGTLive.cursor/rules/async-threading-patterns.mdc · 103Cursor rulescsharpai-agent+2styleuido-not65/1003 days ago
SethRobinson/UGTLive.cursor/rules/code-style-conventions.mdc · 103Cursor rulescsharpai-agent+2stylearchtypesdocs62/1003 days ago
SethRobinson/UGTLive.cursor/rules/configuration-management.mdc · 103Cursor rulescsharpai-agent+2archsecuritydatabaseapi+165/1003 days ago
SethRobinson/UGTLive.cursor/rules/debugging-testing.mdc · 103Cursor rulescsharpai-agent+2buildteststylearch+369/1003 days ago
SethRobinson/UGTLive.cursor/rules/locale-invariant-formatting.mdc · 103Cursor rulescsharpai-agent+2lint-formatuido-not61/1003 days ago
SethRobinson/UGTLive.cursor/rules/translation-workflow.mdc · 103Cursor rulescsharpai-agent+2testlint-formatarchapi+366/1003 days ago
SethRobinson/UGTLive.cursor/rules/ugtlive-project-guide.mdc · 103Cursor rulescsharpai-agent+2stylearchuideployment+169/1003 days ago
SethRobinson/UGTLive.cursor/rules/versioning-workflow.mdc · 103Cursor rulescsharpai-agent+2stylegitdeploymentagent-behaviour+162/1003 days ago
SethRobinson/UGTLive.cursor/rules/wpf-ui-patterns.mdc · 103Cursor rulescsharpai-agent+2setuplint-formatstylearch+166/1003 days ago
SethRobinson/UGTLiveAGENTS.md · 103AGENTS.mdcsharpai-agent+2testgitsecurityperformance+174/1003 days ago
Diff against .cursor/rules/ui-ux-patterns.mdc Diff against .cursor/rules/architecture-patterns.mdc Diff against .cursor/rules/async-threading-patterns.mdc Diff against .cursor/rules/code-style-conventions.mdc Diff against .cursor/rules/configuration-management.mdc Diff against .cursor/rules/debugging-testing.mdc Diff against .cursor/rules/locale-invariant-formatting.mdc Diff against .cursor/rules/translation-workflow.mdc Diff against .cursor/rules/ugtlive-project-guide.mdc Diff against .cursor/rules/versioning-workflow.mdc Diff against .cursor/rules/wpf-ui-patterns.mdc Diff against AGENTS.md

Similar configs

Same format, overlapping stack, ranked by quality.

Same format, overlapping stack, ranked by quality
RepositoryFormatStackCoversScoreChanged
ThanhTrunggDEV/DontBeLazy.cursor/rules/rust-testing.mdc · 6Cursor rulesjavascriptcsharp+2teststyletesting-strategy90/1003 days ago
ThanhTrunggDEV/DontBeLazy.cursor/rules/dart-testing.mdc · 6Cursor rulesjavascriptcsharp+2teststyletypestesting-strategy85/1003 days ago
ThanhTrunggDEV/DontBeLazy.cursor/rules/dart-coding-style.mdc · 6Cursor rulesjavascriptcsharp+2lint-formatstyletypesdo-not84/1003 days ago
ThanhTrunggDEV/DontBeLazy.cursor/rules/rust-security.mdc · 6Cursor rulesjavascriptcsharp+2stylesecuritydatabasedo-not80/1003 days ago
imazen/imageflow.cursor/rules/ci.mdc · 4.4kCursor rulesrustcsharp+2setupbuildtestarch+379/1003 days ago
ThanhTrunggDEV/DontBeLazy.cursor/rules/rust-coding-style.mdc · 6Cursor rulesjavascriptcsharp+2lint-formatstyle78/1003 days ago
ThanhTrunggDEV/DontBeLazy.cursor/rules/dart-hooks.mdc · 6Cursor rulesjavascriptcsharp+2lint-formatarchtesting-strategygit+178/1003 days ago
SethRobinson/UGTLive.cursor/rules/architecture-patterns.mdc · 103Cursor rulescsharpai-agent+2buildtestlint-formatstyle+677/1003 days ago
RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack