Skip to content

Commit bb44a7f

Browse files
committed
status updated
1 parent 23d458e commit bb44a7f

File tree

2 files changed

+114
-47
lines changed

2 files changed

+114
-47
lines changed

commands/coldbox/ai/stats.cfc

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -174,53 +174,67 @@ component extends="coldbox-cli.models.BaseAICommand" {
174174
)
175175
print.line()
176176

177-
// Context Estimate
178-
print.boldWhiteLine( "💾 Estimated AI Context Usage" )
177+
// Context Estimate - Subagent Pattern
178+
print.boldWhiteLine( "💾 AI Context Usage (Subagent Pattern)" )
179179
var contextData = [
180180
[
181-
"Guidelines",
182-
"~#arguments.stats.contextEstimate.guidelinesKB# KB"
181+
"Base Context",
182+
"~#arguments.stats.contextEstimate.baseContextKB# KB",
183+
"Agent files loaded at startup"
183184
],
184185
[
185-
"Skills",
186-
"~#arguments.stats.contextEstimate.skillsKB# KB"
186+
" ├─ Inlined",
187+
"~#arguments.stats.contextEstimate.inlinedKB# KB",
188+
"Core guidelines embedded in agents"
187189
],
188190
[
189-
"Total",
190-
"~#arguments.stats.contextEstimate.totalKB# KB"
191+
" └─ Agent Files",
192+
"~#arguments.stats.contextEstimate.baseContextKB - arguments.stats.contextEstimate.inlinedKB# KB",
193+
"Agent configuration overhead"
194+
],
195+
[
196+
"On-Demand",
197+
"~#arguments.stats.contextEstimate.onDemandKB# KB",
198+
"Available but not loaded (inventoried)"
199+
],
200+
[
201+
"Total Available",
202+
"~#arguments.stats.contextEstimate.totalAvailableKB# KB",
203+
"If all resources were loaded"
191204
]
192205
]
193206
print.table(
194-
headerNames = [ "Component", "Size" ],
207+
headerNames = [ "Component", "Size", "Description" ],
195208
data = contextData
196209
)
197210
print.line()
198211

199-
// Show usage indicator based on common AI models (using GPT-4 128K as baseline)
200-
var estimatedTokens = arguments.stats.contextEstimate.totalKB * 300
212+
// Show usage indicator based on BASE CONTEXT (what's actually loaded)
213+
var estimatedTokens = arguments.stats.contextEstimate.baseContextKB * 300
201214
var baselineTokens = 128000 // GPT-4 context window
202215
var percentage = ( estimatedTokens / baselineTokens ) * 100
203216

204-
print.toConsole( " Usage: " )
217+
print.toConsole( " Base Context Usage: " )
205218
if ( percentage < 30 ) {
206-
print.greenLine( "✓ Low (#numberFormat( percentage, "_._" )#% of typical AI context)" )
219+
printSuccess( "✓ Low (#numberFormat( percentage, "_._" )#% of typical AI context)" )
207220
} else if ( percentage < 60 ) {
208-
print.yellowLine( "⚠ Moderate (#numberFormat( percentage, "_._" )#% of typical AI context)" )
221+
printInfo( "⚠ Moderate (#numberFormat( percentage, "_._" )#% of typical AI context)" )
209222
} else if ( percentage < 90 ) {
210-
print.orangeLine( "⚠ High (#numberFormat( percentage, "_._" )#% of typical AI context)" )
223+
printWarn( "⚠ High (#numberFormat( percentage, "_._" )#% of typical AI context)" )
211224
} else {
212-
print.redLine( "⛔ Very High (#numberFormat( percentage, "_._" )#% of typical AI context)" )
213-
print.dim( " Consider reducing guidelines/skills for better AI performance" )
225+
printError( "⛔ Very High (#numberFormat( percentage, "_._" )#% of typical AI context)" )
226+
print.dimLine( " Consider reducing inlined guidelines for better AI performance" )
214227
}
228+
printHelp( "On-demand resources are loaded only when needed via subagent pattern" )
215229
print.line()
216230

217231
// Context window estimates for popular AI models
218232
if ( arguments.verbose ) {
219233
print.line()
220-
print.cyanLine( "📈 Context Window Utilization:" )
234+
print.cyanLine( "📈 Context Window Utilization (Base Context):" )
221235

222-
// Build table data
223-
var estimatedTokens = arguments.stats.contextEstimate.totalKB * 300
236+
// Build table data - use BASE CONTEXT (what's actually loaded)
237+
var estimatedTokens = arguments.stats.contextEstimate.baseContextKB * 300
224238
var tableData = [
225239
[
226240
"Claude 3.5 Sonnet",
@@ -269,6 +283,8 @@ component extends="coldbox-cli.models.BaseAICommand" {
269283
],
270284
data = tableData
271285
)
286+
print.dim( " * Utilization shown for base context only (agent files + inlined guidelines)" )
287+
print.dim( " * On-demand resources (~#arguments.stats.contextEstimate.onDemandKB# KB) loaded via subagent as needed" )
272288
print.line()
273289
}
274290

models/AIService.cfc

Lines changed: 78 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,9 @@ component singleton {
476476
"custom" : 0,
477477
"override" : 0,
478478
"totalSize" : 0,
479-
"avgSize" : 0
479+
"avgSize" : 0,
480+
"inlinedSize" : 0,
481+
"onDemandSize" : 0
480482
},
481483
"skills" : {
482484
"total" : info.skills.len(),
@@ -489,7 +491,8 @@ component singleton {
489491
},
490492
"agents" : {
491493
"total" : manifest.agents.len(),
492-
"configured" : manifest.agents
494+
"configured" : manifest.agents,
495+
"filesSize" : 0
493496
},
494497
"mcpServers" : {
495498
"total" : 0,
@@ -501,21 +504,64 @@ component singleton {
501504
"templateType" : manifest.templateType ?: "unknown",
502505
"lastSync" : manifest.lastSync ?: "never",
503506
"contextEstimate" : {
504-
"totalKB" : 0,
505-
"guidelinesKB" : 0,
506-
"skillsKB" : 0
507+
"baseContextKB" : 0,
508+
"inlinedKB" : 0,
509+
"onDemandKB" : 0,
510+
"totalAvailableKB" : 0
507511
}
508512
};
509513

510-
// Count guidelines by type
514+
// Determine which guidelines are inlined based on language
515+
var inlinedGuidelines = [ "coldbox" ];
516+
if ( stats.language == "boxlang" || stats.language == "hybrid" ) {
517+
inlinedGuidelines.append( "boxlang" );
518+
}
519+
if ( stats.language == "cfml" || stats.language == "hybrid" ) {
520+
inlinedGuidelines.append( "cfml" );
521+
}
522+
523+
// Count guidelines by type and calculate sizes
524+
var aiDir = arguments.directory & "/.ai";
525+
var guidelinesDir = aiDir & "/guidelines";
511526
info.guidelines.each( ( guideline ) => {
512527
var type = guideline.type ?: "module";
513528
if ( structKeyExists( stats.guidelines, type ) ) {
514529
stats.guidelines[ type ]++;
515530
}
531+
532+
// Calculate if this guideline is inlined or on-demand
533+
if ( type == "core" && inlinedGuidelines.find( guideline.name ) ) {
534+
// Core inlined guideline - calculate actual file size
535+
var guidelineFile = guidelinesDir & "/core/" & guideline.name & ".md";
536+
if ( fileExists( guidelineFile ) ) {
537+
stats.guidelines.inlinedSize += getFileInfo( guidelineFile ).size;
538+
}
539+
} else {
540+
// On-demand guideline - only description counts in base context
541+
// Full file counts toward on-demand total
542+
var guidelinePath = "";
543+
if ( type == "core" ) {
544+
guidelinePath = guidelinesDir & "/core/" & guideline.name & ".md";
545+
} else if ( type == "module" ) {
546+
guidelinePath = guidelinesDir & "/modules/" & guideline.name & ".md";
547+
} else if ( type == "custom" ) {
548+
guidelinePath = guidelinesDir & "/custom/" & guideline.name & ".md";
549+
} else if ( type == "override" ) {
550+
guidelinePath = guidelinesDir & "/overrides/" & guideline.name & ".md";
551+
}
552+
if ( len( guidelinePath ) && fileExists( guidelinePath ) ) {
553+
stats.guidelines.onDemandSize += getFileInfo( guidelinePath ).size;
554+
}
555+
}
516556
} );
517557

518-
// Count skills by type
558+
// Calculate total guidelines size
559+
if ( directoryExists( guidelinesDir ) ) {
560+
stats.guidelines.totalSize = calculateDirectorySize( guidelinesDir );
561+
stats.guidelines.avgSize = stats.guidelines.total > 0 ? int( stats.guidelines.totalSize / stats.guidelines.total ) : 0;
562+
}
563+
564+
// Count skills by type (all skills are on-demand)
519565
info.skills.each( ( skill ) => {
520566
var type = skill.type ?: "module";
521567
var source = skill.source ?: "";
@@ -531,6 +577,14 @@ component singleton {
531577
}
532578
} );
533579

580+
// Skills size (all on-demand)
581+
var skillsDir = aiDir & "/skills";
582+
if ( directoryExists( skillsDir ) ) {
583+
var skillsSize = calculateDirectorySize( skillsDir );
584+
stats.skills.totalSize = skillsSize;
585+
stats.skills.avgSize = stats.skills.total > 0 ? int( skillsSize / stats.skills.total ) : 0;
586+
}
587+
534588
// Count MCP servers
535589
var mcpServers = manifest.mcpServers ?: {
536590
"core" : [],
@@ -542,28 +596,25 @@ component singleton {
542596
stats.mcpServers.custom = mcpServers.custom.len();
543597
stats.mcpServers.total = stats.mcpServers.core + stats.mcpServers.module + stats.mcpServers.custom;
544598

545-
// Calculate file sizes
546-
var aiDir = arguments.directory & "/.ai";
547-
// Guidelines size
548-
var guidelinesDir = aiDir & "/guidelines";
549-
if ( directoryExists( guidelinesDir ) ) {
550-
var guidelineSize = calculateDirectorySize( guidelinesDir );
551-
stats.guidelines.totalSize = guidelineSize;
552-
stats.guidelines.avgSize = stats.guidelines.total > 0 ? int( guidelineSize / stats.guidelines.total ) : 0;
553-
stats.contextEstimate.guidelinesKB = int( guidelineSize / 1024 );
554-
}
555-
556-
// Skills size
557-
var skillsDir = aiDir & "/skills";
558-
if ( directoryExists( skillsDir ) ) {
559-
var skillsSize = calculateDirectorySize( skillsDir );
560-
stats.skills.totalSize = skillsSize;
561-
stats.skills.avgSize = stats.skills.total > 0 ? int( skillsSize / stats.skills.total ) : 0;
562-
stats.contextEstimate.skillsKB = int( skillsSize / 1024 );
599+
// Calculate agent files size (the actual base context)
600+
if ( manifest.agents.len() ) {
601+
manifest.agents.each( ( agent ) => {
602+
var agentPath = variables.agentRegistry.getAgentConfigPath( directory, agent );
603+
if ( fileExists( agentPath ) ) {
604+
stats.agents.filesSize += getFileInfo( agentPath ).size;
605+
}
606+
} );
563607
}
564608

565-
// Total context estimate
566-
stats.contextEstimate.totalKB = stats.contextEstimate.guidelinesKB + stats.contextEstimate.skillsKB;
609+
// Calculate context estimates
610+
// Base context = agent files (includes inlined guidelines + inventories)
611+
stats.contextEstimate.baseContextKB = int( stats.agents.filesSize / 1024 );
612+
// Inlined guidelines (part of base context, shown separately for clarity)
613+
stats.contextEstimate.inlinedKB = int( stats.guidelines.inlinedSize / 1024 );
614+
// On-demand resources (not in base context, but available)
615+
stats.contextEstimate.onDemandKB = int( ( stats.guidelines.onDemandSize + stats.skills.totalSize ) / 1024 );
616+
// Total available if all resources were loaded
617+
stats.contextEstimate.totalAvailableKB = int( ( stats.agents.filesSize + stats.guidelines.onDemandSize + stats.skills.totalSize ) / 1024 );
567618

568619
return stats;
569620
}

0 commit comments

Comments
 (0)