Skip to content

Commit 441b921

Browse files
committed
app detection and more
1 parent dd363b3 commit 441b921

7 files changed

Lines changed: 423 additions & 702 deletions

File tree

commands/coldbox/ai/info.cfc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ component extends="coldbox-cli.models.BaseAICommand" {
3535
print.table(
3636
headerNames = [ "Setting", "Value" ],
3737
data = [
38-
[ "coldbox-cli Version", info.coldboxCliVersion ],
38+
[ "ColdBox CLI Version", info.coldboxCliVersion ],
3939
[ "Language Mode", info.language ],
40+
[ "App Type", info.templateType ],
4041
[ "Active Agent", activeAgent ],
4142
[ "Last Sync", info.lastSync ]
4243
]

models/AIService.cfc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,12 @@ component singleton {
5555
createAIDirectoryStructure( arguments.directory );
5656

5757
// Initialize manifest
58+
var templateType = variables.utility.detectTemplateType( arguments.directory )
5859
var manifest = {
5960
"coldboxCliVersion" : variables.utility.getColdboxCliVersion(),
6061
"lastSync" : dateTimeFormat( now(), "iso" ),
6162
"language" : arguments.language,
63+
"templateType" : templateType,
6264
"guidelines" : [],
6365
"skills" : [],
6466
"agents" : listToArray( arguments.agents )
@@ -131,6 +133,9 @@ component singleton {
131133
manifest.coldboxCliVersion = variables.utility.getColdboxCliVersion()
132134
manifest.lastSync = dateTimeFormat( now(), "iso" )
133135

136+
// Update/add template type (detects current structure, handles old manifests or structure changes)
137+
manifest.templateType = variables.utility.detectTemplateType( arguments.directory )
138+
134139
// Refresh guidelines based on installed modules
135140
var guidelineChanges = variables.guidelineManager.refresh( arguments.directory, manifest );
136141
result.added.append( guidelineChanges.added, true );
@@ -162,6 +167,7 @@ component singleton {
162167
"installed" : structKeyExists( manifest, "coldboxCliVersion" ),
163168
"coldboxCliVersion" : manifest.coldboxCliVersion ?: "unknown",
164169
"language" : manifest.language ?: "unknown",
170+
"templateType" : manifest.templateType ?: "unknown",
165171
"lastSync" : manifest.lastSync ?: "never",
166172
"guidelines" : manifest.guidelines ?: [],
167173
"skills" : manifest.skills ?: [],

models/AgentRegistry.cfc

Lines changed: 108 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# |PROJECT_NAME| - AI Agent Instructions
2+
3+
This is a ColdBox HMVC application using the **flat template structure** where all application code lives in the webroot. Compatible with Adobe ColdFusion 2018+, Lucee 5.x+, and BoxLang 1.0+.
4+
5+
## Project Overview
6+
7+
**Language Mode:** |LANGUAGE_MODE|
8+
**ColdBox Version:** |COLDBOX_VERSION|
9+
**Template Type:** Flat (traditional webroot structure)
10+
11+
## Application Structure
12+
13+
```
14+
/ - Application root (webroot)
15+
├── Application.cfc - Bootstrap that directly loads ColdBox
16+
├── index.cfm - Front controller
17+
├── config/ - Framework and app configuration
18+
├── handlers/ - Event handlers (controllers)
19+
├── models/ - Service objects, business logic
20+
├── views/ - HTML templates
21+
├── layouts/ - Page layouts wrapping views
22+
├── includes/ - Public assets (CSS, JS, images)
23+
├── modules_app/ - Application modules (HMVC)
24+
├── tests/ - Test suites
25+
└── lib/ - Framework dependencies
26+
```
27+
28+
**Key Characteristics:**
29+
- Everything in webroot (simpler for traditional hosting)
30+
- No `/app` vs `/public` separation
31+
- All code is web-accessible by default
32+
- `COLDBOX_APP_MAPPING = ""` (empty, app at root)
33+
34+
## Framework Knowledge
35+
36+
**Important:** For ColdBox framework documentation, refer to the **ColdBox guideline** which covers:
37+
- Event handlers and routing
38+
- Request context (event object)
39+
- Dependency injection (WireBox)
40+
- Interceptors (AOP)
41+
- Modules
42+
- Configuration patterns
43+
44+
Additional framework guidelines are available for TestBox, WireBox, CacheBox, and LogBox.
45+
46+
## Project-Specific Conventions
47+
48+
### Code Style
49+
50+
- **Semicolons:** Optional in CFML/BoxLang. Only use when demarcating properties or in inline component syntax
51+
- **Handler naming:** Plural nouns (Users.cfc, Orders.cfc)
52+
- **Service naming:** Descriptive with "Service" suffix (UserService.cfc)
53+
- **Dependency injection:** Use `property name="service" inject` over manual getInstance()
54+
55+
### Testing
56+
57+
- Tests located in `/tests/specs/`
58+
- Integration tests extend `BaseTestCase` with `appMapping="/app"`
59+
- **Critical:** Always call `setup()` in `beforeEach()` for test isolation
60+
- Run tests: `box testbox run`
61+
62+
### Configuration
63+
64+
- Environment variables defined in `.env` (copy from `.env.example`)
65+
- Access via `getSystemSetting("VAR_NAME", "default")`
66+
- Framework config in `config/ColdBox.cfc`
67+
- Routes in `config/Router.cfc`
68+
69+
### Application Helpers
70+
71+
- `includes/helpers/ApplicationHelper.cfm` - Available in all handlers/views
72+
- Add common utility functions here
73+
74+
### Development Workflow
75+
76+
```bash
77+
# Install dependencies
78+
box install
79+
80+
# Start server
81+
box server start
82+
83+
# Format code
84+
box run-script format
85+
86+
# Run tests
87+
box testbox run
88+
89+
# Reinit framework (dev)
90+
/?fwreinit=true
91+
```
92+
93+
## Custom Application Details
94+
95+
<!-- Add project-specific information below -->
96+
97+
### Business Domain
98+
99+
<!-- Describe what this application does -->
100+
101+
### Key Services/Models
102+
103+
<!-- List important services and their responsibilities -->
104+
105+
### Authentication/Security
106+
107+
<!-- Describe authentication approach if applicable -->
108+
109+
### API Endpoints
110+
111+
<!-- Document REST API routes if applicable -->
112+
113+
### Deployment
114+
115+
<!-- Document deployment process -->
116+
117+
### Third-Party Integrations
118+
119+
<!-- List external services, APIs, or integrations -->
120+
121+
## Important Notes
122+
123+
- Framework reinit: Use `?fwreinit=true` or configure `reinitPassword` for production
124+
- Module routes process before app routes - be aware of conflicts
125+
- Use PRC for internal data, RC only for user input
126+
- Always validate user input from RC
127+
128+
## Additional Resources
129+
130+
- ColdBox Docs: https://coldbox.ortusbooks.com
131+
- TestBox: https://testbox.ortusbooks.com
132+
- WireBox: https://wirebox.ortusbooks.com

0 commit comments

Comments
 (0)