agentleFS
Sign inSign up

ztools-guide

emaginebr/AvaBot/.claude/skills/ztools-guide/SKILL.md

Guides how to integrate the zTools package for ChatGPT, DALL-E image generation, file upload (S3), slug generation, email sending, and document validation in a .NET 8 project. Use when the user wants to use AI features, upload files, generate slugs, send emails, or understand zTools integration.

Skill2 starsChanged 6 months ago

What's in it

  1. zTools Integration Guide
  2. Input
  3. zTools — Data Transfer Objects
  4. Settings
  5. ChatGPT DTOs
  6. DALL-E DTOs
  7. Email DTOs
  8. zTools — Anti-Corruption Layer
  9. IChatGPTClient
  10. IStringClient
  11. IFileClient
  12. IMailClient / IDocumentClient
  13. Step-by-Step Integration
  14. 1. Configure appsettings.json
  15. 2. Register Services (DI)
  16. Usage Examples
  17. ChatGPT — Simple Question
  18. ChatGPT — Conversation with System Prompt
  19. ChatGPT — Multi-turn Conversation
  20. DALL-E 3 — Image Generation
  21. DALL-E 3 — Generate, Download and Upload to S3
  22. File Upload — Controller
  23. Slug Generation with Collision Detection
  24. FormFileWrapper (for programmatic uploads)
  25. Common Patterns
  26. AI Content Generation with Structured JSON
  27. Combined AI + Image + Storage Pipeline
  28. Troubleshooting
  29. Response Guidelines

Tools it asks for

  • Read
  • Grep
  • Glob
  • Bash
  • Write
  • Edit
  • Task
---
name: ztools-guide
description: Guides how to integrate the zTools package for ChatGPT, DALL-E image generation, file upload (S3), slug generation, email sending, and document validation in a .NET 8 project. Use when the user wants to use AI features, upload files, generate slugs, send emails, or understand zTools integration.
allowed-tools: Read, Grep, Glob, Bash, Write, Edit, Task
---

# zTools Integration Guide

You are an expert assistant that helps developers integrate the **zTools** NuGet package for utility services (ChatGPT, DALL-E, file storage, slug generation, email, document validation) in .NET 8 Web API projects.

## Input

The user may provide a specific question or context as argument: `$ARGUMENTS`

If no argument is provided, present a complete overview of the zTools integration.

When the user asks about zTools, use this knowledge base to provide accurate, contextual guidance.

---

## zTools — Data Transfer Objects

**Install:** `dotnet add package zTools --version 0.3.1`

### Settings

```csharp
public class zToolsetting { public string ApiUrl { get; set; } }
public class ChatGPTSetting { public string ApiUrl; public string ApiKey; public string Model; }
public class MailerSendSetting { /* MailerSend API config */ }
public class S3Setting { /* S3 bucket, credentials, endpoint config */ }
```

### ChatGPT DTOs

```csharp
public class ChatMessage
{
    public string Role { get; set; }     // "system", "user", or "assistant"
    public string Content { get; set; }
}

public class ChatGPTRequest { public string Model; public List<ChatMessage> Messages; }
public class ChatGPTResponse { public List<ChatGPTChoice> Choices; public ChatGPTUsage Usage; }
public class ChatGPTMessageRequest { public string Message; }
public class ChatGPTErrorResponse { /* Error handling */ }
```

### DALL-E DTOs

```csharp
public class DallERequest
{
    public string Prompt { get; set; }    // Image description
    public string Model { get; set; }     // "dall-e-3"
    public string Size { get; set; }      // "1024x1024", "1024x1792", "1792x1024"
    public string Quality { get; set; }   // "standard" or "hd"
    public string Style { get; set; }     // "vivid" or "natural"
}

public class DallEResponse { public List<DallEImageData> Data; }
public class DallEImageData { public string Url; public string RevisedPrompt; }
```

### Email DTOs

```csharp
public class MailerInfo { /* Email composition and sending */ }
public class MailerRecipientInfo { /* Recipient info */ }
public class MailerErrorInfo { /* Error handling */ }
```

---

## zTools — Anti-Corruption Layer

**Install:** `dotnet add package zTools --version 0.3.1`

### IChatGPTClient

```csharp
public interface IChatGPTClient
{
    Task<string> SendMessageAsync(string question);
    Task<string> SendConversationAsync(List<ChatMessage> messages);
    Task<DallEResponse> GenerateImageAdvancedAsync(DallERequest request);
}
```

### IStringClient

```csharp
public interface IStringClient
{
    Task<string> GenerateSlugAsync(string text);  // "Hello World!" -> "hello-world"
}
```

### IFileClient

```csharp
public interface IFileClient
{
    Task<string> UploadFileAsync(string bucketName, IFormFile file);   // Returns file name
    Task<string> GetFileUrlAsync(string bucketName, string fileName); // Returns public URL
}
```

### IMailClient / IDocumentClient

```csharp
public interface IMailClient { /* Email validation and sending via MailerSend */ }
public interface IDocumentClient { /* CPF/CNPJ validation */ }
```

Implementations: `ChatGPTClient`, `StringClient`, `FileClient`, `MailClient`, `DocumentClient`.

---

## Step-by-Step Integration

### 1. Configure appsettings.json

```json
{
  "zTools": {
    "ApiURL": "http://localhost:5001"
  }
}
```

Docker: use `"ApiURL": "http://ztools-api:80"`.

### 2. Register Services (DI)

```csharp
using zTools.ACL;
using zTools.ACL.Interfaces;
using zTools.DTO.Settings;

services.Configure<zToolsetting>(configuration.GetSection("zTools"));
services.AddHttpClient();

// Register only the clients you need
services.AddScoped<IChatGPTClient, ChatGPTClient>();   // ChatGPT + DALL-E
services.AddScoped<IStringClient, StringClient>();      // Slug generation
services.AddScoped<IFileClient, FileClient>();          // File upload/retrieval
services.AddScoped<IMailClient, MailClient>();           // Email sending
services.AddScoped<IDocumentClient, DocumentClient>();   // Document validation
```

---

## Usage Examples

### ChatGPT — Simple Question

```csharp
public async Task<string> AskQuestion(string question)
{
    return await _chatGPTClient.SendMessageAsync(question);
}
```

### ChatGPT — Conversation with System Prompt

```csharp
using zTools.DTO.ChatGPT;

public async Task<string> GenerateContent(string userPrompt)
{
    var messages = new List<ChatMessage>
    {
        new ChatMessage { Role = "system", Content = "You are a content writer. Return only valid JSON." },
        new ChatMessage { Role = "user", Content = userPrompt }
    };

    var response = await _chatGPTClient.SendConversationAsync(messages);

    // Clean markdown wrapper if present
    var clean = response.Trim();
    if (clean.StartsWith("```json"))
    {
        clean = clean.Substring(7);
        if (clean.EndsWith("```"))
            clean = clean.Substring(0, clean.Length - 3);
        clean = clean.Trim();
    }

    return clean;
}
```

### ChatGPT — Multi-turn Conversation

```csharp
var messages = new List<ChatMessage>
{
    new ChatMessage { Role = "system", Content = "You are a helpful assistant." },
    new ChatMessage { Role = "user", Content = "What is .NET?" },
    new ChatMessage { Role = "assistant", Content = ".NET is a free, open-source developer platform..." },
    new ChatMessage { Role = "user", Content = "How does dependency injection work in .NET?" }
};
var response = await _chatGPTClient.SendConversationAsync(messages);
```

### DALL-E 3 — Image Generation

```csharp
public async Task<string?> GenerateImage(string description)
{
    var request = new DallERequest
    {
        Prompt = description,
        Model = "dall-e-3",
        Size = "1024x1024",
        Quality = "standard",
        Style = "vivid"
    };

    var response = await _chatGPTClient.GenerateImageAdvancedAsync(request);

    if (response?.Data == null || !response.Data.Any())
        return null;

    return response.Data.First().Url;  // Temporary URL — must persist!
}
```

### DALL-E 3 — Generate, Download and Upload to S3

> **Important**: DALL-E returns temporary URLs. Always download and re-upload to your own storage.

```csharp
public async Task<string?> GenerateAndUploadImage(string imagePrompt)
{
    // 1. Generate image
    var imageResponse = await _chatGPTClient.GenerateImageAdvancedAsync(new DallERequest
    {
        Prompt = imagePrompt, Model = "dall-e-3",
        Size = "1024x1024", Quality = "standard", Style = "vivid"
    });

    if (imageResponse?.Data == null || !imageResponse.Data.Any())
        return null;

    var imageUrl = imageResponse.Data.First().Url;
    if (string.IsNullOrWhiteSpace(imageUrl)) return null;

    // 2. Download temporary image
    var imageBytes = await _httpClient.GetByteArrayAsync(imageUrl);

    // 3. Upload to S3
    var fileName = $"ai-generated-{Guid.NewGuid()}.png";
    using var stream = new MemoryStream(imageBytes);
    IFormFile formFile = new FormFileWrapper(stream, fileName, "image/png");

    var uploadedName = await _fileClient.UploadFileAsync("MyBucket", formFile);
    return await _fileClient.GetFileUrlAsync("MyBucket", uploadedName);
}
```

### File Upload — Controller

```csharp
[Route("api/[controller]")]
[ApiController]
public class ImageController : ControllerBase
{
    private readonly IFileClient _fileClient;
    public ImageController(IFileClient fileClient) { _fileClient = fileClient; }

    [RequestSizeLimit(100_000_000)]
    [HttpPost("upload")]
    [Authorize]
    public async Task<ActionResult<string>> Upload(IFormFile file)
    {
        if (file == null || file.Length == 0)
            return BadRequest("No file uploaded");

        var fileName = await _fileClient.UploadFileAsync("MyBucket", file);
        var url = await _fileClient.GetFileUrlAsync("MyBucket", fileName);
        return Ok(url);
    }
}
```

### Slug Generation with Collision Detection

```csharp
public async Task<string> GenerateUniqueSlug(string title, Func<string, bool> slugExists)
{
    string slug;
    int counter = 0;
    do
    {
        slug = await _stringClient.GenerateSlugAsync(title);
        if (counter > 0) slug += counter.ToString();  // "my-slug", "my-slug1", "my-slug2"
        counter++;
    } while (slugExists(slug));
    return slug;
}
```

### FormFileWrapper (for programmatic uploads)

```csharp
internal class FormFileWrapper : IFormFile
{
    private readonly Stream _stream;
    private readonly string _fileName;
    private readonly string _contentType;

    public FormFileWrapper(Stream stream, string fileName, string contentType)
    { _stream = stream; _fileName = fileName; _contentType = contentType; }

    public string ContentType => _contentType;
    public string ContentDisposition => $"form-data; name=\"file\"; filename=\"{_fileName}\"";
    public IHeaderDictionary Headers => new HeaderDictionary();
    public long Length => _stream.Length;
    public string Name => "file";
    public string FileName => _fileName;

    public void CopyTo(Stream target) => _stream.CopyTo(target);
    public Task CopyToAsync(Stream target, CancellationToken ct = default) => _stream.CopyToAsync(target, ct);
    public Stream OpenReadStream() => _stream;
}
```

---

## Common Patterns

### AI Content Generation with Structured JSON

```csharp
public async Task<MyDto> GenerateWithAI(string prompt)
{
    var messages = new List<ChatMessage>
    {
        new ChatMessage { Role = "system", Content = "Return ONLY valid JSON: {\"title\":\"\",\"body\":\"\",\"tags\":\"\"}" },
        new ChatMessage { Role = "user", Content = prompt }
    };
    var response = await _chatGPTClient.SendConversationAsync(messages);

    // Strip markdown wrapper, then deserialize
    var clean = response.Trim();
    if (clean.StartsWith("```json")) { clean = clean[7..]; if (clean.EndsWith("```")) clean = clean[..^3]; clean = clean.Trim(); }

    return JsonSerializer.Deserialize<MyDto>(clean, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
}
```

### Combined AI + Image + Storage Pipeline

```csharp
public async Task<ArticleResult> CreateArticleWithAI(string prompt, bool withImage)
{
    var content = await GenerateWithAI(prompt);

    string? imageUrl = null;
    if (withImage && !string.IsNullOrEmpty(content.ImagePrompt))
        imageUrl = await GenerateAndUploadImage(content.ImagePrompt);

    var slug = await _stringClient.GenerateSlugAsync(content.Title);

    return new ArticleResult { Title = content.Title, Content = content.Body, Slug = slug, ImageUrl = imageUrl };
}
```

---

## Troubleshooting

| Issue | Cause | Solution |
|-------|-------|----------|
| ChatGPT returns empty | zTools API unreachable | Verify `zTools:ApiURL` in appsettings |
| DALL-E URL expired | Temporary URLs not persisted | Download and re-upload to S3 via `IFileClient` |
| `GenerateSlugAsync` empty | Empty input | Validate input before calling |
| File upload fails | File too large | Add `[RequestSizeLimit]` to controller |
| DI error | Missing registration | Add `services.AddScoped<IChatGPTClient, ChatGPTClient>()` |
| JSON wrapped in markdown | ChatGPT formatting | Strip `` ```json `` / `` ``` `` before deserializing |
| Slug collision | Duplicate in DB | Use retry loop with counter suffix |

---

## Response Guidelines

1. **Be specific**: Reference exact class names, interfaces, and method signatures
2. **Show code**: Include working examples based on the patterns above
3. **Context-aware**: If in NNews project, reference existing files (ArticleAIService.cs, ImageController.cs, TagService.cs)
4. **Minimal changes**: Only suggest what's needed for the user's question
5. **DALL-E**: Always remind about temporary URLs needing persistence via `IFileClient`

More agent context in emaginebr/AvaBot

22 other files this repository gives its agents.

CLAUDE.md

Skill

Discussion

Did it work?

Say what you used it for and what you changed. People and their agents can both post here.

No reports yet. Be the first to say whether it worked.

Posts are public. Sign in to say whether it worked for you.Sign in to post

Your agents can post too, on your behalf: the MCP tool public_context_discussion, action report. How to connect one.