@@ -112,8 +112,8 @@ component singleton {
112112 required string language
113113 ){
114114 var configPath = getAgentConfigPath ( arguments .directory , arguments .agent )
115- var layout = detectProjectLayout ( arguments .directory )
116- var content = getAgentConfigContent ( arguments .agent , arguments .language , layout )
115+ var templateType = variables . utility . detectTemplateType ( arguments .directory )
116+ var content = getAgentConfigContent ( arguments .agent , arguments .language , templateType , arguments . directory )
117117
118118 // Create directories if needed
119119 var configDir = getDirectoryFromPath ( configPath )
@@ -166,56 +166,132 @@ component singleton {
166166 *
167167 * @agent The agent name (claude, copilot, cursor, etc.)
168168 * @language Project language mode (boxlang, cfml, hybrid)
169- * @layout Project layout type (flat or modern)
169+ * @templateType Project template type (flat or modern)
170+ * @directory The project directory
170171 */
171- private function getAgentConfigContent( required string agent , required string language , required string layout ){
172+ private function getAgentConfigContent(
173+ required string agent ,
174+ required string language ,
175+ required string templateType ,
176+ required string directory
177+ ){
172178 var templatesPath = variables .utility .getTemplatesPath ()
173179 var templateFile = " "
174180
175- // For copilot, use layout-specific templates
176- if ( arguments .agent == " copilot" ) {
177- templateFile = arguments .layout == " modern"
178- ? " #templatesPath #/ai/modern-copilot-instructions.md"
179- : " #templatesPath #/ai/flat-copilot-instructions.md"
180- } else {
181- // Use generic template for other agents
182- templateFile = " #templatesPath #/ai/agents/agent-instructions.md"
183- }
181+ // Use layout-specific templates for all agents
182+ templateFile = arguments .templateType == " modern"
183+ ? " #templatesPath #/ai/agents/agent-modern-instructions.md"
184+ : " #templatesPath #/ai/agents/agent-flat-instructions.md"
184185
185186 if ( ! fileExists ( templateFile ) ) {
186- // Fallback content from template
187- var fallbackPath = templatesPath & " /ai/agents/agent-fallback.md"
188- var fallback = fileRead ( fallbackPath )
187+ throw (
188+ type = " AgentRegistry.TemplateNotFound" ,
189+ message = " Agent template not found: #templateFile #"
190+ )
191+ }
189192
190- // Replace tokens
191- fallback = replaceNoCase ( fallback , " |agentName|" , arguments .agent , " all" )
192- fallback = replaceNoCase ( fallback , " |language|" , arguments .language , " all" )
193- fallback = replaceNoCase ( fallback , " |layout|" , arguments .layout , " all" )
193+ var content = fileRead ( templateFile )
194194
195- return fallback
195+ // Get project information
196+ var boxJson = {}
197+ var boxJsonPath = " #arguments .directory #/box.json"
198+ if ( fileExists ( boxJsonPath ) ) {
199+ boxJson = deserializeJSON ( fileRead ( boxJsonPath ) )
196200 }
197201
198- var content = fileRead ( templateFile )
202+ var projectName = boxJson .name ?: getFileFromPath ( arguments .directory )
203+ var coldboxVersion = boxJson .dependencies .coldbox ?: " 8.x"
204+
205+ // Determine language mode display
206+ var languageMode = " BoxLang"
207+ if ( arguments .language == " cfml" ) {
208+ languageMode = " CFML"
209+ } else if ( arguments .language == " hybrid" ) {
210+ languageMode = " BoxLang/CFML Hybrid"
211+ }
212+
213+ // Detect enabled features
214+ var viteEnabled = detectViteEnabled ( arguments .directory )
215+ var dockerEnabled = detectDockerEnabled ( arguments .directory )
216+ var ormEnabled = detectOrmEnabled ( boxJson )
217+ var migrationsEnabled = detectMigrationsEnabled ( arguments .directory , boxJson )
218+
219+ // Build features list
220+ var enabledFeatures = []
221+ if ( viteEnabled ) enabledFeatures .append ( " Vite" )
222+ if ( dockerEnabled ) enabledFeatures .append ( " Docker" )
223+ if ( ormEnabled ) enabledFeatures .append ( " ORM" )
224+ if ( migrationsEnabled ) enabledFeatures .append ( " Migrations" )
225+
226+ var features = enabledFeatures .len () ? enabledFeatures .toList ( " , " ) : " None"
199227
200228 // Replace placeholders
201- var languageNote = arguments .language == " boxlang" ? " BoxLang" : ( arguments .language == " cfml" ? " CFML" : " BoxLang/CFML hybrid" )
202- content = replaceNoCase ( content , " |LANGUAGE|" , languageNote , " all" )
229+ content = replaceNoCase ( content , " |PROJECT_NAME|" , projectName , " all" )
230+ content = replaceNoCase ( content , " |LANGUAGE_MODE|" , languageMode , " all" )
231+ content = replaceNoCase ( content , " |COLDBOX_VERSION|" , coldboxVersion , " all" )
232+ content = replaceNoCase ( content , " |FEATURES|" , features , " all" )
233+ content = replaceNoCase ( content , " |VITE_ENABLED|" , viteEnabled ? " Yes" : " No" , " all" )
234+ content = replaceNoCase ( content , " |DOCKER_ENABLED|" , dockerEnabled ? " Yes" : " No" , " all" )
235+ content = replaceNoCase ( content , " |ORM_ENABLED|" , ormEnabled ? " Yes" : " No" , " all" )
236+ content = replaceNoCase ( content , " |MIGRATIONS_ENABLED|" , migrationsEnabled ? " Yes" : " No" , " all" )
203237
204238 return content
205239 }
206240
207241 /**
208- * Detect project layout type
209- *
210- * @directory The project directory
242+ * Detect if Vite is enabled in the project
243+ */
244+ private function detectViteEnabled( required string directory ){
245+ var viteConfig = " #arguments .directory #/vite.config.mjs"
246+ var packageJson = " #arguments .directory #/package.json"
247+
248+ if ( fileExists ( viteConfig ) ) return true
249+
250+ if ( fileExists ( packageJson ) ) {
251+ var pkgContent = deserializeJSON ( fileRead ( packageJson ) )
252+ return structKeyExists ( pkgContent .dependencies ?: {}, " vite" ) ||
253+ structKeyExists ( pkgContent .devDependencies ?: {}, " vite" )
254+ }
255+
256+ return false
257+ }
258+
259+ /**
260+ * Detect if Docker is enabled in the project
211261 */
212- private function detectProjectLayout ( required string directory ){
213- // Modern layout has separate /app and /public directories
214- var hasAppDir = directoryExists ( " #arguments .directory #/app " )
215- var hasPublicDir = directoryExists ( " # arguments . directory #/public " )
262+ private function detectDockerEnabled ( required string directory ){
263+ return fileExists ( " # arguments . directory #/Dockerfile " ) ||
264+ fileExists ( " #arguments .directory #/docker-compose.yml " )
265+ }
216266
217- return ( hasAppDir && hasPublicDir ) ? " modern" : " flat"
267+ /**
268+ * Detect if ORM is enabled (cborm or quick)
269+ */
270+ private function detectOrmEnabled( required struct boxJson ){
271+ var deps = boxJson .dependencies ?: {}
272+ var devDeps = boxJson .devDependencies ?: {}
273+
274+ return structKeyExists ( deps , " cborm" ) ||
275+ structKeyExists ( devDeps , " cborm" ) ||
276+ structKeyExists ( deps , " quick" ) ||
277+ structKeyExists ( devDeps , " quick" )
218278 }
219279
280+ /**
281+ * Detect if migrations are enabled
282+ */
283+ private function detectMigrationsEnabled( required string directory , required struct boxJson ){
284+ // Check for migrations in dependencies
285+ var deps = boxJson .dependencies ?: {}
286+ var devDeps = boxJson .devDependencies ?: {}
287+
288+ if ( structKeyExists ( deps , " commandbox-migrations" ) ||
289+ structKeyExists ( devDeps , " commandbox-migrations" ) ) {
290+ return true
291+ }
292+
293+ // Check for migrations directory
294+ return directoryExists ( " #arguments .directory #/resources/database/migrations" )
295+ }
220296
221297}
0 commit comments