@polymorphism-tech/morph-spec 1.0.4 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/CLAUDE.md +1381 -0
  2. package/LICENSE +72 -0
  3. package/README.md +89 -6
  4. package/bin/detect-agents.js +225 -0
  5. package/bin/morph-spec.js +120 -0
  6. package/bin/render-template.js +302 -0
  7. package/bin/semantic-detect-agents.js +246 -0
  8. package/bin/validate-agents-skills.js +239 -0
  9. package/bin/validate-agents.js +69 -0
  10. package/bin/validate-phase.js +263 -0
  11. package/content/.azure/README.md +293 -0
  12. package/content/.azure/docs/azure-devops-setup.md +454 -0
  13. package/content/.azure/docs/branch-strategy.md +398 -0
  14. package/content/.azure/docs/local-development.md +515 -0
  15. package/content/.azure/pipelines/pipeline-variables.yml +34 -0
  16. package/content/.azure/pipelines/prod-pipeline.yml +319 -0
  17. package/content/.azure/pipelines/staging-pipeline.yml +234 -0
  18. package/content/.azure/pipelines/templates/build-dotnet.yml +75 -0
  19. package/content/.azure/pipelines/templates/deploy-app-service.yml +94 -0
  20. package/content/.azure/pipelines/templates/deploy-container-app.yml +120 -0
  21. package/content/.azure/pipelines/templates/infra-deploy.yml +90 -0
  22. package/content/.claude/commands/morph-apply.md +118 -26
  23. package/content/.claude/commands/morph-archive.md +9 -9
  24. package/content/.claude/commands/morph-clarify.md +184 -0
  25. package/content/.claude/commands/morph-design.md +275 -0
  26. package/content/.claude/commands/morph-proposal.md +56 -15
  27. package/content/.claude/commands/morph-setup.md +100 -0
  28. package/content/.claude/commands/morph-status.md +47 -32
  29. package/content/.claude/commands/morph-tasks.md +319 -0
  30. package/content/.claude/commands/morph-uiux.md +211 -0
  31. package/content/.claude/skills/specialists/ai-system-architect.md +604 -0
  32. package/content/.claude/skills/specialists/ms-agent-expert.md +143 -89
  33. package/content/.claude/skills/specialists/ui-ux-designer.md +744 -9
  34. package/content/.claude/skills/stacks/dotnet-blazor.md +244 -8
  35. package/content/.claude/skills/stacks/dotnet-nextjs.md +2 -2
  36. package/content/.morph/.morphversion +5 -0
  37. package/content/.morph/config/agents.json +101 -8
  38. package/content/.morph/config/azure-pricing.json +70 -0
  39. package/content/.morph/config/azure-pricing.schema.json +50 -0
  40. package/content/.morph/config/config.template.json +15 -3
  41. package/content/.morph/docs/STORY-DRIVEN-DEVELOPMENT.md +392 -0
  42. package/content/.morph/hooks/README.md +239 -0
  43. package/content/.morph/hooks/pre-commit-agents.sh +24 -0
  44. package/content/.morph/hooks/pre-commit-all.sh +48 -0
  45. package/content/.morph/hooks/pre-commit-costs.sh +91 -0
  46. package/content/.morph/hooks/pre-commit-specs.sh +49 -0
  47. package/content/.morph/hooks/pre-commit-tests.sh +60 -0
  48. package/content/.morph/project.md +5 -4
  49. package/content/.morph/schemas/agent.schema.json +296 -0
  50. package/content/.morph/standards/agent-framework-setup.md +453 -0
  51. package/content/.morph/standards/architecture.md +142 -7
  52. package/content/.morph/standards/azure.md +218 -23
  53. package/content/.morph/standards/coding.md +47 -12
  54. package/content/.morph/standards/dotnet10-migration.md +494 -0
  55. package/content/.morph/standards/fluent-ui-setup.md +590 -0
  56. package/content/.morph/standards/migration-guide.md +514 -0
  57. package/content/.morph/standards/passkeys-auth.md +423 -0
  58. package/content/.morph/standards/vector-search-rag.md +536 -0
  59. package/content/.morph/state.json +18 -0
  60. package/content/.morph/templates/FluentDesignTheme.cs +149 -0
  61. package/content/.morph/templates/MudTheme.cs +281 -0
  62. package/content/.morph/templates/contracts.cs +55 -55
  63. package/content/.morph/templates/decisions.md +4 -4
  64. package/content/.morph/templates/design-system.css +226 -0
  65. package/content/.morph/templates/infra/.dockerignore.example +89 -0
  66. package/content/.morph/templates/infra/Dockerfile.example +82 -0
  67. package/content/.morph/templates/infra/README.md +286 -0
  68. package/content/.morph/templates/infra/app-service.bicep +164 -0
  69. package/content/.morph/templates/infra/deploy.ps1 +229 -0
  70. package/content/.morph/templates/infra/deploy.sh +208 -0
  71. package/content/.morph/templates/infra/main.bicep +41 -7
  72. package/content/.morph/templates/infra/parameters.dev.json +6 -0
  73. package/content/.morph/templates/infra/parameters.prod.json +6 -0
  74. package/content/.morph/templates/infra/parameters.staging.json +29 -0
  75. package/content/.morph/templates/proposal.md +3 -3
  76. package/content/.morph/templates/recap.md +3 -3
  77. package/content/.morph/templates/spec.md +9 -8
  78. package/content/.morph/templates/sprint-status.yaml +68 -0
  79. package/content/.morph/templates/state.template.json +222 -0
  80. package/content/.morph/templates/story.md +143 -0
  81. package/content/.morph/templates/tasks.md +1 -1
  82. package/content/.morph/templates/ui-components.md +276 -0
  83. package/content/.morph/templates/ui-design-system.md +286 -0
  84. package/content/.morph/templates/ui-flows.md +336 -0
  85. package/content/.morph/templates/ui-mockups.md +133 -0
  86. package/content/.morph/test-infra/example.bicep +59 -0
  87. package/content/CLAUDE.md +124 -0
  88. package/content/README.md +79 -0
  89. package/detectors/config-detector.js +223 -0
  90. package/detectors/conversation-analyzer.js +163 -0
  91. package/detectors/index.js +84 -0
  92. package/detectors/standards-generator.js +275 -0
  93. package/detectors/structure-detector.js +221 -0
  94. package/docs/README.md +149 -0
  95. package/docs/api/cost-calculator.js.html +513 -0
  96. package/docs/api/design-system-generator.js.html +382 -0
  97. package/docs/api/fonts/Montserrat/Montserrat-Bold.eot +0 -0
  98. package/docs/api/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
  99. package/docs/api/fonts/Montserrat/Montserrat-Bold.woff +0 -0
  100. package/docs/api/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
  101. package/docs/api/fonts/Montserrat/Montserrat-Regular.eot +0 -0
  102. package/docs/api/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
  103. package/docs/api/fonts/Montserrat/Montserrat-Regular.woff +0 -0
  104. package/docs/api/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
  105. package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
  106. package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +978 -0
  107. package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
  108. package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
  109. package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
  110. package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
  111. package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1049 -0
  112. package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
  113. package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
  114. package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
  115. package/docs/api/global.html +5263 -0
  116. package/docs/api/index.html +96 -0
  117. package/docs/api/scripts/collapse.js +39 -0
  118. package/docs/api/scripts/commonNav.js +28 -0
  119. package/docs/api/scripts/linenumber.js +25 -0
  120. package/docs/api/scripts/nav.js +12 -0
  121. package/docs/api/scripts/polyfill.js +4 -0
  122. package/docs/api/scripts/prettify/Apache-License-2.0.txt +202 -0
  123. package/docs/api/scripts/prettify/lang-css.js +2 -0
  124. package/docs/api/scripts/prettify/prettify.js +28 -0
  125. package/docs/api/scripts/search.js +99 -0
  126. package/docs/api/state-manager.js.html +423 -0
  127. package/docs/api/styles/jsdoc.css +776 -0
  128. package/docs/api/styles/prettify.css +80 -0
  129. package/docs/examples.md +328 -0
  130. package/docs/getting-started.md +302 -0
  131. package/docs/installation.md +361 -0
  132. package/docs/templates.md +418 -0
  133. package/docs/validation-checklist.md +266 -0
  134. package/package.json +39 -12
  135. package/src/commands/cost.js +181 -0
  136. package/src/commands/create-story.js +283 -0
  137. package/src/commands/detect.js +104 -0
  138. package/src/commands/doctor.js +67 -0
  139. package/src/commands/generate.js +149 -0
  140. package/src/commands/init.js +69 -45
  141. package/src/commands/shard-spec.js +224 -0
  142. package/src/commands/sprint-status.js +250 -0
  143. package/src/commands/state.js +333 -0
  144. package/src/commands/sync.js +167 -0
  145. package/src/commands/update-pricing.js +206 -0
  146. package/src/commands/update.js +88 -13
  147. package/src/lib/complexity-analyzer.js +292 -0
  148. package/src/lib/cost-calculator.js +429 -0
  149. package/src/lib/design-system-generator.js +298 -0
  150. package/src/lib/state-manager.js +340 -0
  151. package/src/utils/file-copier.js +59 -0
  152. package/src/utils/version-checker.js +175 -0
@@ -0,0 +1,453 @@
1
+ # Microsoft Agent Framework - Setup Obrigatório (.NET 10)
2
+
3
+ > **IMPORTANTE:** O MORPH-SPEC usa **exclusivamente** o Microsoft Agent Framework.
4
+ > Semantic Kernel foi descontinuado. Não use mais.
5
+
6
+ ---
7
+
8
+ ## 📦 Packages Necessários
9
+
10
+ ```xml
11
+ <!-- .csproj -->
12
+ <PackageReference Include="Microsoft.Agents.AI" Version="1.0.0" />
13
+ ```
14
+
15
+ **Nota:** O package `Microsoft.Agents.AI` já traz as dependências:
16
+ - `Microsoft.Extensions.AI`
17
+ - `OpenAI` (cliente)
18
+ - Suporte a múltiplos providers (Azure OpenAI, GitHub Models, Ollama)
19
+
20
+ ---
21
+
22
+ ## ⚙️ Configuração no Program.cs
23
+
24
+ ### 1. Registrar ChatClient (Azure OpenAI)
25
+
26
+ ```csharp
27
+ using Microsoft.Extensions.AI;
28
+
29
+ var builder = WebApplication.CreateBuilder(args);
30
+
31
+ // Registrar ChatClient como singleton
32
+ builder.Services.AddSingleton<IChatClient>(sp =>
33
+ {
34
+ var config = sp.GetRequiredService<IConfiguration>();
35
+
36
+ return new ChatClient(
37
+ model: "gpt-4o-mini", // Modelo padrão para tasks simples
38
+ credential: new ApiKeyCredential(config["AzureOpenAI:ApiKey"]!),
39
+ endpoint: new Uri(config["AzureOpenAI:Endpoint"]!)
40
+ );
41
+ });
42
+ ```
43
+
44
+ ### 2. Registrar ChatClient (GitHub Models - Desenvolvimento)
45
+
46
+ ```csharp
47
+ builder.Services.AddSingleton<IChatClient>(sp =>
48
+ {
49
+ var config = sp.GetRequiredService<IConfiguration>();
50
+
51
+ return new ChatClient(
52
+ model: "gpt-4.1-mini",
53
+ credential: new ApiKeyCredential(config["GitHub:Token"]!),
54
+ endpoint: new Uri("https://models.github.com")
55
+ );
56
+ });
57
+ ```
58
+
59
+ ### 3. Registrar ChatClient (Ollama - Local)
60
+
61
+ ```csharp
62
+ builder.Services.AddSingleton<IChatClient>(sp =>
63
+ {
64
+ return new ChatClient(
65
+ model: "llama3.2:3b",
66
+ endpoint: new Uri("http://localhost:11434")
67
+ );
68
+ });
69
+ ```
70
+
71
+ **Escolha o provider adequado ao ambiente.**
72
+
73
+ ---
74
+
75
+ ## 🤖 Pattern de Agent (Obrigatório)
76
+
77
+ ### Interface do Agent
78
+
79
+ ```csharp
80
+ public interface IOrderAnalysisAgent
81
+ {
82
+ Task<string> AnalyzeAsync(Order order, CancellationToken ct = default);
83
+ }
84
+ ```
85
+
86
+ ### Implementação do Agent
87
+
88
+ ```csharp
89
+ using Microsoft.Agents.AI;
90
+
91
+ public class OrderAnalysisAgent : IOrderAnalysisAgent
92
+ {
93
+ private readonly IChatClient _chatClient;
94
+ private readonly ILogger<OrderAnalysisAgent> _logger;
95
+
96
+ public OrderAnalysisAgent(
97
+ IChatClient chatClient,
98
+ ILogger<OrderAnalysisAgent> logger)
99
+ {
100
+ _chatClient = chatClient;
101
+ _logger = logger;
102
+ }
103
+
104
+ public async Task<string> AnalyzeAsync(Order order, CancellationToken ct = default)
105
+ {
106
+ // Criar agente com instruções específicas
107
+ var agent = _chatClient.CreateAgent(
108
+ instructions: """
109
+ Você é um especialista em análise de pedidos de e-commerce.
110
+
111
+ Analise o pedido fornecido e retorne:
112
+ 1. Resumo do pedido
113
+ 2. Sugestões de upsell baseadas nos itens
114
+ 3. Risco de cancelamento (baixo/médio/alto) com justificativa
115
+
116
+ Seja conciso e objetivo.
117
+ """,
118
+ name: "OrderAnalyzer"
119
+ );
120
+
121
+ // Criar prompt com dados do pedido
122
+ var prompt = $"""
123
+ Pedido: {order.OrderNumber}
124
+ Total: {order.Total:C}
125
+ Itens: {order.Items.Count}
126
+ Cliente: {order.Customer.Name}
127
+ Histórico: {order.Customer.TotalOrders} pedidos anteriores
128
+
129
+ Analise este pedido.
130
+ """;
131
+
132
+ _logger.LogInformation("Analisando pedido {OrderNumber}", order.OrderNumber);
133
+
134
+ // Executar agente
135
+ var response = await agent.RunAsync(prompt, cancellationToken: ct);
136
+
137
+ return response.Content;
138
+ }
139
+ }
140
+ ```
141
+
142
+ ### Registrar Agent como Service
143
+
144
+ ```csharp
145
+ // Program.cs
146
+ builder.Services.AddScoped<IOrderAnalysisAgent, OrderAnalysisAgent>();
147
+ ```
148
+
149
+ ---
150
+
151
+ ## 🔧 Agents com Tools (Function Calling)
152
+
153
+ ### Definir Tools
154
+
155
+ ```csharp
156
+ public class WeatherAgent
157
+ {
158
+ private readonly IChatClient _chatClient;
159
+ private readonly IWeatherService _weatherService;
160
+
161
+ public WeatherAgent(IChatClient chatClient, IWeatherService weatherService)
162
+ {
163
+ _chatClient = chatClient;
164
+ _weatherService = weatherService;
165
+ }
166
+
167
+ // Tool 1: Buscar clima
168
+ [AgentTool("get_weather")]
169
+ [Description("Busca o clima atual de uma cidade")]
170
+ public async Task<string> GetWeatherAsync(
171
+ [Description("Nome da cidade")] string city,
172
+ CancellationToken ct = default)
173
+ {
174
+ var weather = await _weatherService.GetCurrentWeatherAsync(city, ct);
175
+ return $"Temp: {weather.Temperature}°C, Condição: {weather.Condition}";
176
+ }
177
+
178
+ // Tool 2: Previsão
179
+ [AgentTool("get_forecast")]
180
+ [Description("Busca a previsão para os próximos dias")]
181
+ public async Task<string> GetForecastAsync(
182
+ [Description("Nome da cidade")] string city,
183
+ [Description("Número de dias")] int days = 3,
184
+ CancellationToken ct = default)
185
+ {
186
+ var forecast = await _weatherService.GetForecastAsync(city, days, ct);
187
+ return string.Join("\n", forecast.Select(f => $"{f.Date:dd/MM}: {f.Temperature}°C"));
188
+ }
189
+
190
+ public async Task<string> ChatAsync(string userMessage, CancellationToken ct = default)
191
+ {
192
+ // Criar agente com tools
193
+ var agent = _chatClient.CreateAgent(
194
+ instructions: """
195
+ Você é um assistente de clima.
196
+ Use as tools disponíveis para responder perguntas sobre o tempo.
197
+ Seja amigável e informativo.
198
+ """,
199
+ name: "WeatherAssistant",
200
+ tools: new[]
201
+ {
202
+ AgentTool.FromMethod(nameof(GetWeatherAsync), this),
203
+ AgentTool.FromMethod(nameof(GetForecastAsync), this)
204
+ }
205
+ );
206
+
207
+ var response = await agent.RunAsync(userMessage, cancellationToken: ct);
208
+ return response.Content;
209
+ }
210
+ }
211
+ ```
212
+
213
+ **Nota:** Cada método com `[AgentTool]` vira uma tool que o agente pode chamar automaticamente.
214
+
215
+ ---
216
+
217
+ ## 💬 Threads (Persistência de Conversação)
218
+
219
+ ### Criar e Usar Thread
220
+
221
+ ```csharp
222
+ public class ChatService
223
+ {
224
+ private readonly IChatClient _chatClient;
225
+ private readonly Dictionary<string, AgentThread> _threads = new();
226
+
227
+ public async Task<string> StartConversationAsync(string userId)
228
+ {
229
+ var agent = _chatClient.CreateAgent(
230
+ instructions: "Você é um assistente útil e amigável.",
231
+ name: "ChatAssistant"
232
+ );
233
+
234
+ // Criar thread
235
+ var thread = await agent.CreateThreadAsync();
236
+
237
+ // Armazenar thread ID para o usuário
238
+ _threads[userId] = thread;
239
+
240
+ return thread.Id;
241
+ }
242
+
243
+ public async Task<string> SendMessageAsync(
244
+ string userId,
245
+ string message,
246
+ CancellationToken ct = default)
247
+ {
248
+ if (!_threads.TryGetValue(userId, out var thread))
249
+ throw new InvalidOperationException("Thread não encontrada");
250
+
251
+ var agent = _chatClient.CreateAgent(
252
+ instructions: "Você é um assistente útil e amigável.",
253
+ name: "ChatAssistant"
254
+ );
255
+
256
+ // Adicionar mensagem do usuário
257
+ await thread.AddMessageAsync(message, ct);
258
+
259
+ // Executar agente no contexto do thread
260
+ var response = await agent.RunAsync(thread, cancellationToken: ct);
261
+
262
+ // Histórico é mantido automaticamente
263
+ return response.Content;
264
+ }
265
+ }
266
+ ```
267
+
268
+ **Vantagem:** Threads mantêm todo o histórico da conversa automaticamente.
269
+
270
+ ---
271
+
272
+ ## 🔄 Multi-Agent Communication (A2A)
273
+
274
+ ### Agent-to-Agent Pattern
275
+
276
+ ```csharp
277
+ public class ResearchAgent
278
+ {
279
+ private readonly IChatClient _chatClient;
280
+
281
+ public async Task<string> ResearchTopicAsync(string topic)
282
+ {
283
+ // Agent 1: Researcher
284
+ var researcher = _chatClient.CreateAgent(
285
+ instructions: "Você pesquisa tópicos e fornece informações detalhadas.",
286
+ name: "Researcher"
287
+ );
288
+
289
+ // Agent 2: Summarizer
290
+ var summarizer = _chatClient.CreateAgent(
291
+ instructions: "Você resume textos longos de forma concisa.",
292
+ name: "Summarizer"
293
+ );
294
+
295
+ // Passo 1: Pesquisar
296
+ var research = await researcher.RunAsync($"Pesquise sobre: {topic}");
297
+
298
+ // Passo 2: Resumir resultado da pesquisa
299
+ var summary = await summarizer.RunAsync(
300
+ $"Resuma o seguinte texto:\n\n{research.Content}"
301
+ );
302
+
303
+ return summary.Content;
304
+ }
305
+ }
306
+ ```
307
+
308
+ ---
309
+
310
+ ## 📊 Modelos Recomendados
311
+
312
+ | Uso | Modelo | Provider | Custo |
313
+ |-----|--------|----------|-------|
314
+ | Tarefas simples | gpt-4o-mini | Azure OpenAI | $0.15/1M input |
315
+ | Análise complexa | gpt-4o | Azure OpenAI | $2.50/1M input |
316
+ | Desenvolvimento local | llama3.2:3b | Ollama | Grátis |
317
+ | Desenvolvimento cloud | gpt-4.1-mini | GitHub Models | Grátis (beta) |
318
+
319
+ **Padrão MORPH-SPEC:** `gpt-4o-mini` para produção.
320
+
321
+ ---
322
+
323
+ ## 🔐 Segurança
324
+
325
+ ### API Keys no Azure Key Vault
326
+
327
+ ```csharp
328
+ // Program.cs
329
+ if (builder.Environment.IsProduction())
330
+ {
331
+ var keyVaultUri = new Uri(builder.Configuration["KeyVault:Uri"]!);
332
+ builder.Configuration.AddAzureKeyVault(keyVaultUri, new DefaultAzureCredential());
333
+ }
334
+
335
+ builder.Services.AddSingleton<IChatClient>(sp =>
336
+ {
337
+ var config = sp.GetRequiredService<IConfiguration>();
338
+
339
+ // API Key vem do Key Vault em produção
340
+ var apiKey = config["AzureOpenAI:ApiKey"]!;
341
+ var endpoint = config["AzureOpenAI:Endpoint"]!;
342
+
343
+ return new ChatClient(
344
+ model: "gpt-4o-mini",
345
+ credential: new ApiKeyCredential(apiKey),
346
+ endpoint: new Uri(endpoint)
347
+ );
348
+ });
349
+ ```
350
+
351
+ ### Managed Identity (Recomendado)
352
+
353
+ ```csharp
354
+ builder.Services.AddSingleton<IChatClient>(sp =>
355
+ {
356
+ var config = sp.GetRequiredService<IConfiguration>();
357
+ var endpoint = config["AzureOpenAI:Endpoint"]!;
358
+
359
+ return new ChatClient(
360
+ model: "gpt-4o-mini",
361
+ credential: new DefaultAzureCredential(), // Managed Identity
362
+ endpoint: new Uri(endpoint)
363
+ );
364
+ });
365
+ ```
366
+
367
+ ---
368
+
369
+ ## 📈 Observabilidade com .NET Aspire
370
+
371
+ ### Integrar com Aspire Dashboard
372
+
373
+ ```csharp
374
+ // Program.cs
375
+ builder.Services.AddOpenTelemetry()
376
+ .WithTracing(tracing =>
377
+ {
378
+ tracing.AddSource("Microsoft.Agents.AI");
379
+ tracing.AddAspireTracing();
380
+ })
381
+ .WithMetrics(metrics =>
382
+ {
383
+ metrics.AddMeter("Microsoft.Agents.AI");
384
+ metrics.AddAspireMetrics();
385
+ });
386
+ ```
387
+
388
+ **Resultado:** Visualize chamadas a agentes e tools no Aspire Dashboard.
389
+
390
+ ---
391
+
392
+ ## ⚠️ Limitações e Troubleshooting
393
+
394
+ ### Tool Calling com Modelos Pequenos
395
+
396
+ **Problema:** Modelos abaixo de 3B parâmetros não fazem tool calling bem.
397
+
398
+ **Solução:** Use `gpt-4o-mini` (mínimo) para agents com tools.
399
+
400
+ ### Rate Limits
401
+
402
+ ```csharp
403
+ public async Task<string> AnalyzeWithRetryAsync(Order order, CancellationToken ct = default)
404
+ {
405
+ var retryPolicy = Policy
406
+ .Handle<RateLimitException>()
407
+ .WaitAndRetryAsync(3, attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)));
408
+
409
+ return await retryPolicy.ExecuteAsync(async () =>
410
+ {
411
+ var agent = _chatClient.CreateAgent(...);
412
+ var response = await agent.RunAsync(..., cancellationToken: ct);
413
+ return response.Content;
414
+ });
415
+ }
416
+ ```
417
+
418
+ ---
419
+
420
+ ## ✅ Checklist de Implementação
421
+
422
+ - [ ] Package `Microsoft.Agents.AI` instalado
423
+ - [ ] `IChatClient` registrado como singleton
424
+ - [ ] Agents criados com `client.CreateAgent()`
425
+ - [ ] Agents registrados como services (scoped/transient)
426
+ - [ ] API keys no Key Vault (produção)
427
+ - [ ] Logging configurado para agents
428
+ - [ ] Observabilidade com Aspire (opcional)
429
+ - [ ] Error handling para rate limits
430
+ - [ ] Testes de integração para agents
431
+
432
+ ---
433
+
434
+ ## 🚫 O Que NÃO Fazer
435
+
436
+ ❌ Usar Semantic Kernel
437
+ ❌ Usar `Kernel.CreateFunctionFromPrompt()`
438
+ ❌ Usar `ChatHistory` (use Threads)
439
+ ❌ Hardcoded API keys
440
+ ❌ Modelos pequenos (<3B) para tool calling
441
+
442
+ ---
443
+
444
+ ## 📚 Referências
445
+
446
+ - [Microsoft Agent Framework Documentation](https://learn.microsoft.com/agent-framework/)
447
+ - [Agent Framework GitHub](https://github.com/microsoft/agent-framework)
448
+ - [Microsoft.Extensions.AI](https://learn.microsoft.com/dotnet/ai/ai-extensions)
449
+ - [Azure OpenAI Service](https://learn.microsoft.com/azure/ai-services/openai/)
450
+
451
+ ---
452
+
453
+ *MORPH-SPEC by Polymorphism Tech*
@@ -147,19 +147,29 @@ services.AddHttpClient<IMemberKitClient, MemberKitClient>(client =>
147
147
 
148
148
  ---
149
149
 
150
- ## 🤖 Agents como Services
150
+ ## 🤖 Agents como Services (.NET 10)
151
+
152
+ > **IMPORTANTE:** Use exclusivamente Microsoft Agent Framework.
151
153
 
152
154
  ```csharp
153
155
  // Agents/DependencyInjection.cs
156
+ using Microsoft.Extensions.AI;
157
+
154
158
  public static IServiceCollection AddAgents(this IServiceCollection services, IConfiguration configuration)
155
159
  {
156
- var builder = Kernel.CreateBuilder();
157
- builder.AddAzureOpenAIChatCompletion(
158
- deploymentName: "gpt-4o-mini",
159
- endpoint: configuration["AzureOpenAI:Endpoint"]!,
160
- apiKey: configuration["AzureOpenAI:ApiKey"]!);
160
+ // Registrar ChatClient
161
+ services.AddSingleton<IChatClient>(sp =>
162
+ {
163
+ var config = sp.GetRequiredService<IConfiguration>();
161
164
 
162
- services.AddSingleton(builder.Build());
165
+ return new ChatClient(
166
+ model: "gpt-4o-mini",
167
+ credential: new ApiKeyCredential(config["AzureOpenAI:ApiKey"]!),
168
+ endpoint: new Uri(config["AzureOpenAI:Endpoint"]!)
169
+ );
170
+ });
171
+
172
+ // Registrar agents como services
163
173
  services.AddScoped<IReportAnalyzerAgent, ReportAnalyzerAgent>();
164
174
 
165
175
  return services;
@@ -173,8 +183,133 @@ public class ReportGeneratorJob(IReportAnalyzerAgent analyzer)
173
183
  var analysis = await analyzer.AnalyzeAsync(data, ct);
174
184
  }
175
185
  }
186
+
187
+ // Implementação do agent
188
+ public class ReportAnalyzerAgent : IReportAnalyzerAgent
189
+ {
190
+ private readonly IChatClient _chatClient;
191
+
192
+ public ReportAnalyzerAgent(IChatClient chatClient)
193
+ {
194
+ _chatClient = chatClient;
195
+ }
196
+
197
+ public async Task<string> AnalyzeAsync(object data, CancellationToken ct)
198
+ {
199
+ var agent = _chatClient.CreateAgent(
200
+ instructions: "Você é um especialista em análise de relatórios...",
201
+ name: "ReportAnalyzer"
202
+ );
203
+
204
+ var response = await agent.RunAsync($"Analise: {data}", cancellationToken: ct);
205
+ return response.Content;
206
+ }
207
+ }
176
208
  ```
177
209
 
210
+ **Referência completa:** [Agent Framework Setup](./agent-framework-setup.md)
211
+
212
+ ---
213
+
214
+ ## 🎨 UI Component Libraries
215
+
216
+ ### Decisão Arquitetural (ADR)
217
+
218
+ **Contexto:**
219
+ Projetos Blazor no MORPH-SPEC precisam de componentes UI consistentes, especialmente para features AI-first.
220
+
221
+ **Decisão:**
222
+ - **Padrão recomendado:** Fluent UI Blazor para projetos AI-first
223
+ - **Alternativa:** MudBlazor para SaaS tradicional
224
+ - **Híbrido:** Permitido quando justificado
225
+
226
+ **Razões:**
227
+
228
+ | Critério | Fluent UI | MudBlazor |
229
+ |----------|-----------|-----------|
230
+ | **AI Components** | ✅ Nativos (chat, streaming) | ❌ Não tem |
231
+ | **Microsoft Integration** | ✅ Agent Framework, Aspire | ❌ Terceiro |
232
+ | **Performance** | ✅ ~200KB | ⚠️ ~500KB |
233
+ | **Componentes** | ⚠️ ~50 | ✅ ~140 |
234
+ | **Future-proof** | ✅ Microsoft mantém | ❓ Comunidade |
235
+
236
+ **Consequências:**
237
+ - ✅ Melhor integração com stack Microsoft (.NET 10, Agent Framework)
238
+ - ✅ Performance otimizada (menor bundle)
239
+ - ✅ UX consistente com produtos Microsoft (Copilot, Teams)
240
+ - ⚠️ Pode precisar MudBlazor para grids/charts complexos
241
+ - ⚠️ Menos templates prontos que MudBlazor
242
+
243
+ ### Matriz de Decisão
244
+
245
+ | Tipo de Projeto | UI Library Recomendada |
246
+ |-----------------|------------------------|
247
+ | SaaS com AI/chat | **Fluent UI** |
248
+ | SaaS com analytics pesados | **Fluent UI + MudBlazor** |
249
+ | Dashboard tradicional | **MudBlazor** |
250
+ | Admin panel simples | **Fluent UI** |
251
+ | Produto enterprise complexo | **Fluent UI + MudBlazor** |
252
+
253
+ ### Pattern de Uso Híbrido
254
+
255
+ ```csharp
256
+ // Program.cs - Registrar ambas libs
257
+ builder.Services.AddFluentUIComponents();
258
+ builder.Services.AddMudServices(); // Só se necessário
259
+ ```
260
+
261
+ ```razor
262
+ <!-- Usar Fluent UI para estrutura principal -->
263
+ <FluentLayout>
264
+ <FluentHeader>
265
+ <FluentToolbar>...</FluentToolbar>
266
+ </FluentHeader>
267
+
268
+ <FluentNavMenu>
269
+ <FluentNavLink>...</FluentNavLink>
270
+ </FluentNavMenu>
271
+
272
+ <FluentMain>
273
+ <!-- Usar MudBlazor para componentes específicos -->
274
+ <MudDataGrid T="Order" ...>
275
+ <!-- Grid complexo -->
276
+ </MudDataGrid>
277
+
278
+ <MudChart>
279
+ <!-- Charts analytics -->
280
+ </MudChart>
281
+
282
+ <!-- Voltar para Fluent UI para AI -->
283
+ <FluentMessageBar>
284
+ AI response
285
+ </FluentMessageBar>
286
+ </FluentMain>
287
+ </FluentLayout>
288
+ ```
289
+
290
+ ### Checklist de Escolha
291
+
292
+ **Use Fluent UI quando:**
293
+ - [ ] Projeto tem features de AI/chat
294
+ - [ ] Integração com Agent Framework
295
+ - [ ] Performance é prioridade
296
+ - [ ] UX tipo Copilot/Microsoft 365
297
+ - [ ] Budget de bundle size limitado
298
+
299
+ **Adicione MudBlazor quando:**
300
+ - [ ] Precisa de DataGrid avançado (filtros, agrupamento, export)
301
+ - [ ] Dashboards com charts customizados
302
+ - [ ] Componentes que Fluent UI não oferece
303
+ - [ ] Time já conhece MudBlazor
304
+
305
+ **Use MudBlazor 100% quando:**
306
+ - [ ] Projeto não tem AI
307
+ - [ ] Já existe codebase MudBlazor
308
+ - [ ] Precisa de 100+ componentes diferentes
309
+ - [ ] Material Design é requisito
310
+
311
+ **Referência completa:** [Fluent UI Setup](./fluent-ui-setup.md)
312
+
178
313
  ---
179
314
 
180
315
  ## ✅ Checklist de Arquitetura