1111using MaIN . Domain . Models . Abstract ;
1212using MaIN . Docs . Api . Models ;
1313using Microsoft . Extensions . Options ;
14- using DomainModels = MaIN . Domain . Models . Models ;
1514
1615namespace MaIN . Docs . Api . Services ;
1716
@@ -21,6 +20,7 @@ public class DocsAgentOrchestrator(
2120 GitHubService githubService ,
2221 CapacityService capacityService ,
2322 IOptions < CapacitySettings > capacityOptions ,
23+ IOptions < ModelSettings > modelOptions ,
2424 IConfiguration configuration ,
2525 ILogger < DocsAgentOrchestrator > logger )
2626{
@@ -44,6 +44,7 @@ private async Task InitializeForTierAsync(int tier)
4444 PrTools . Init ( githubService ) ;
4545
4646 var settings = capacityOptions . Value ;
47+ var models = modelOptions . Value ;
4748 var geminiKey1 = configuration [ "MaIN:GeminiKey" ] ?? "" ;
4849
4950 string modelChatty , modelCode , modelReview , modelDesign , modelForge ;
@@ -81,11 +82,11 @@ private async Task InitializeForTierAsync(int tier)
8182 cfg . BackendType = BackendType . Gemini ;
8283 cfg . GeminiKey = settings . Tier2 . GeminiKey ;
8384 } ) ;
84- modelChatty = DomainModels . Gemini . Gemini3_1FlashLite ;
85- modelCode = DomainModels . Gemini . Gemini3_1FlashLite ;
86- modelReview = DomainModels . Gemini . Gemini3_1FlashLite ;
87- modelDesign = DomainModels . Gemini . Gemini3_1FlashLite ;
88- modelForge = DomainModels . Gemini . Gemini3_1FlashLite ;
85+ modelChatty = models . Tier2 . Chatty ;
86+ modelCode = models . Tier2 . Code ;
87+ modelReview = models . Tier2 . Review ;
88+ modelDesign = models . Tier2 . Design ;
89+ modelForge = models . Tier2 . Forge ;
8990 logger . LogInformation ( "[Capacity] Initializing agents for Tier 2 (low) — Flash Lite on secondary key" ) ;
9091 }
9192 else
@@ -95,11 +96,11 @@ private async Task InitializeForTierAsync(int tier)
9596 cfg . BackendType = BackendType . Gemini ;
9697 cfg . GeminiKey = geminiKey1 ;
9798 } ) ;
98- modelChatty = DomainModels . Gemini . Gemini3_1FlashLite ;
99- modelCode = DomainModels . Gemini . Gemini3_5Flash ;
100- modelReview = DomainModels . Gemini . Gemini3_5Flash ;
101- modelDesign = DomainModels . Gemini . Gemini3_1ProPreview ;
102- modelForge = DomainModels . Gemini . Gemini3_1ProPreview ;
99+ modelChatty = models . Tier1 . Chatty ;
100+ modelCode = models . Tier1 . Code ;
101+ modelReview = models . Tier1 . Review ;
102+ modelDesign = models . Tier1 . Design ;
103+ modelForge = models . Tier1 . Forge ;
103104 logger . LogInformation ( "[Capacity] Initializing agents for Tier 1 (normal) — standard Gemini stack" ) ;
104105 }
105106
@@ -108,7 +109,13 @@ private async Task InitializeForTierAsync(int tier)
108109 // output. With no MaxTokens set, that budget can be exhausted entirely by reasoning
109110 // across multi-step tool-call turns, leaving both Content and the FullAnswer token
110111 // empty. Give every Gemini-backed agent more headroom.
111- var geminiParams = tier < 3 ? new GeminiInferenceParams { MaxTokens = 16384 } : null ;
112+ var geminiAdditionalParams = new Dictionary < string , object > ( ) ;
113+ if ( ! string . IsNullOrWhiteSpace ( settings . ReasoningEffort ) )
114+ geminiAdditionalParams [ "reasoning_effort" ] = settings . ReasoningEffort ;
115+
116+ var geminiParams = tier < 3
117+ ? new GeminiInferenceParams { MaxTokens = 16384 , AdditionalParams = geminiAdditionalParams }
118+ : null ;
112119
113120 var chattyTools = BuildChattyTools ( docsPath ) ;
114121 var codeTools = BuildCodeTools ( docsPath ) ;
@@ -234,6 +241,8 @@ public async Task<AgentResult> ProcessAsync(
234241 docsRead . Add ( path ) ;
235242 toolResultChars += contentLength ;
236243 } ) ;
244+ var readPaths = new HashSet < string > ( StringComparer . OrdinalIgnoreCase ) ;
245+ MdTools . SetReadDedup ( readPaths ) ;
237246
238247 if ( agentId == "code" )
239248 {
@@ -373,6 +382,7 @@ async Task<AgentResult> Core(IAgentContextExecutor agentCtx)
373382
374383 docsRead . Clear ( ) ;
375384 toolResultChars = 0 ;
385+ readPaths . Clear ( ) ;
376386 artifactUrl = null ; artifactProposed = null ;
377387 issueUrl = null ; issueProposed = null ; planProposed = null ;
378388 reviewProposed = null ; reviewPosted = null ; codeChangeProposed = null ;
@@ -397,6 +407,7 @@ async Task<AgentResult> Core(IAgentContextExecutor agentCtx)
397407 PrTools . SetPrCapture ( null ) ;
398408 PrTools . SetPrUrlCapture ( null ) ;
399409 MdTools . SetReadCapture ( null ) ;
410+ MdTools . SetReadDedup ( null ) ;
400411 sem . Release ( ) ;
401412 }
402413 }
@@ -865,7 +876,7 @@ private static ToolsConfiguration BuildCodeTools(string docsPath) =>
865876 required = new [ ] { "archiveName" , "description" , "kind" }
866877 } ,
867878 ArtifactTools . Propose )
868- . WithMaxIterations ( 10 )
879+ . WithMaxIterations ( 18 )
869880 . WithToolChoice ( "auto" )
870881 . Build ( ) ;
871882
@@ -1243,7 +1254,10 @@ FRAMEWORK FACTS (don't guess, verify via tools):
12431254 - Console bootstrap: MaINBootstrapper.Initialize(); ASP.NET: services.AddMaIN(configuration)
12441255 - MCP has 3 integration styles: direct prompt, agent pipeline step, RAG knowledge source
12451256
1246- TOOL ECONOMY: You have 10 tool slots. list_docs (1) → read app-template doc + maybe 1 more (2) → show_file × N files (N) → propose_artifact_generation (1) = done. Never read the same file twice.
1257+ TOOL ECONOMY: You have 18 tool slots. list_docs (1) → read app-template doc + maybe 1 more (2) → show_file × N files (N) → propose_artifact_generation (1) = done.
1258+ NEVER call read_md_file twice for the same path — its content is already in an earlier tool
1259+ result in this conversation, re-requesting it just wastes your tool budget and gets you closer
1260+ to running out before propose_artifact_generation.
12471261
12481262 TOOLS — use them every time, no improvising:
12491263 1. list_docs — discover what files exist
@@ -1315,6 +1329,18 @@ before writing any code. Do not assume console.
13151329 solution (showing the new files per the ARTIFACTS rules) before calling
13161330 propose_artifact_generation / generate_artifact again.
13171331
1332+ DESKTOP VISUAL QUALITY — when kind is "desktop", app-template-desktop.md's "Modern
1333+ visual style — gradients & glass panels" and "Common AVLN2000 / XAML compile errors"
1334+ sections are part of the SAME read_md_file call as the rest of the template — apply
1335+ both. Pick an accent palette and layout shape that fit THIS app's topic (a weather
1336+ app, a recipe app, a budgeting app must not all look like the same blue chat window):
1337+ use a gradient header/hero, "glass" Border cards, and an accent color on primary
1338+ buttons, and shape the main layout (dashboard grid, list+detail, single tool view —
1339+ not always Chat+Settings tabs) around the app's actual feature. Before calling
1340+ show_file on any .axaml file, check every Padding/CornerRadius/BoxShadow/Spacing
1341+ usage against the AVLN2000 pitfalls section — wrap panels in a Border rather than
1342+ setting those directly on StackPanel/Grid/WrapPanel/DockPanel.
1343+
13181344 CONFIG PROMPTING — every generated app MUST let the user supply backend config (model
13191345 path/Ollama URL for local, API keys + model names for cloud) at runtime, never hardcoded:
13201346 - console: interactive Console.ReadLine() setup wizard (see app-template-console.md)
0 commit comments