fraim-framework 2.0.75 โ 2.0.77
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.
- package/README.md +12 -105
- package/bin/fraim-mcp.js +1 -1
- package/dist/src/cli/commands/add-ide.js +15 -17
- package/dist/src/cli/commands/init-project.js +41 -48
- package/dist/src/cli/commands/override.js +11 -1
- package/dist/src/cli/setup/auto-mcp-setup.js +15 -19
- package/dist/src/cli/setup/codex-local-config.js +37 -0
- package/dist/src/cli/setup/mcp-config-generator.js +94 -11
- package/dist/src/core/config-loader.js +6 -9
- package/dist/src/core/types.js +2 -19
- package/dist/src/local-mcp-server/stdio-server.js +758 -228
- package/package.json +116 -109
package/README.md
CHANGED
|
@@ -66,7 +66,7 @@ R - Retrospectives: Continuous learning from experience
|
|
|
66
66
|
|
|
67
67
|
### โ
**The FRAIM Solution**
|
|
68
68
|
|
|
69
|
-
#### ๐ก๏ธ **Agent Integrity & Test Ethics**
|
|
69
|
+
#### ๐ก๏ธ **Agent Integrity & Test Ethics**
|
|
70
70
|
**Problem**: Agents claim "tests pass" when they actually fail
|
|
71
71
|
**Solution**: Mandatory evidence collection, test immutability rules, and accountability frameworks
|
|
72
72
|
```bash
|
|
@@ -74,7 +74,7 @@ R - Retrospectives: Continuous learning from experience
|
|
|
74
74
|
# After FRAIM: "Here's the test output proving all 47 tests pass"
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
#### ๐งช **Comprehensive Testing Guidelines**
|
|
77
|
+
#### ๐งช **Comprehensive Testing Guidelines**
|
|
78
78
|
**Problem**: Superficial testing that misses real issues
|
|
79
79
|
**Solution**: Multi-layer validation (database, API, UI, integration) with mandatory evidence
|
|
80
80
|
```bash
|
|
@@ -82,7 +82,7 @@ R - Retrospectives: Continuous learning from experience
|
|
|
82
82
|
# After: Test real systems, prove it works, show evidence
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
#### ๐ฃ๏ธ **Clear Communication Standards**
|
|
85
|
+
#### ๐ฃ๏ธ **Clear Communication Standards**
|
|
86
86
|
**Problem**: Vague progress reports and unclear accountability
|
|
87
87
|
**Solution**: Structured progress updates with concrete evidence and absolute accountability
|
|
88
88
|
```bash
|
|
@@ -90,7 +90,7 @@ R - Retrospectives: Continuous learning from experience
|
|
|
90
90
|
# After: "Fixed API timeout, tests passing, evidence attached, ready for review"
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
#### ๐๏ธ **Architectural Discipline**
|
|
93
|
+
#### ๐๏ธ **Architectural Discipline**
|
|
94
94
|
**Problem**: Agents create architectural chaos and technical debt
|
|
95
95
|
**Solution**: Clean separation of concerns, type safety, and testability patterns
|
|
96
96
|
```bash
|
|
@@ -98,7 +98,7 @@ R - Retrospectives: Continuous learning from experience
|
|
|
98
98
|
# After: Clean layers with proper boundaries and validation
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
-
#### ๐ฏ **Spike-First Development**
|
|
101
|
+
#### ๐ฏ **Spike-First Development**
|
|
102
102
|
**Problem**: Agents build complex solutions without validating assumptions
|
|
103
103
|
**Solution**: 5-15 minute proof-of-concepts before major implementation
|
|
104
104
|
```bash
|
|
@@ -106,7 +106,7 @@ R - Retrospectives: Continuous learning from experience
|
|
|
106
106
|
# After: 10-minute spike, validate approach, then build confidently
|
|
107
107
|
```
|
|
108
108
|
|
|
109
|
-
#### ๐ **Continuous Learning System**
|
|
109
|
+
#### ๐ **Continuous Learning System**
|
|
110
110
|
**Problem**: Same mistakes repeated across projects
|
|
111
111
|
**Solution**: Retrospective-driven knowledge capture and pattern recognition
|
|
112
112
|
```bash
|
|
@@ -114,7 +114,7 @@ R - Retrospectives: Continuous learning from experience
|
|
|
114
114
|
# After: Knowledge accumulates, patterns emerge, quality improves
|
|
115
115
|
```
|
|
116
116
|
|
|
117
|
-
#### ๐งน **Simplicity Discipline**
|
|
117
|
+
#### ๐งน **Simplicity Discipline**
|
|
118
118
|
**Problem**: Over-engineered solutions that are hard to maintain
|
|
119
119
|
**Solution**: "Keep it simple" principles with complexity budgets
|
|
120
120
|
```bash
|
|
@@ -122,7 +122,7 @@ R - Retrospectives: Continuous learning from experience
|
|
|
122
122
|
# After: Minimal, focused solution that actually works
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
-
#### ๐ง **Git Safety & Timeout Management**
|
|
125
|
+
#### ๐ง **Git Safety & Timeout Management**
|
|
126
126
|
**Problem**: Agents hang on interactive Git commands and long-running tasks, requiring human intervention
|
|
127
127
|
**Solution**: Safe Git commands and timeout scripts with output visibility
|
|
128
128
|
```bash
|
|
@@ -131,7 +131,7 @@ R - Retrospectives: Continuous learning from experience
|
|
|
131
131
|
# Example: exec-with-timeout.ts runs tests with timeout and saves output to files
|
|
132
132
|
```
|
|
133
133
|
|
|
134
|
-
#### ๐ **Merge Requirements & Branch Safety**
|
|
134
|
+
#### ๐ **Merge Requirements & Branch Safety**
|
|
135
135
|
**Problem**: Agents accidentally overwrite master branch or create merge conflicts
|
|
136
136
|
**Solution**: Mandatory rebase workflows with conflict resolution patterns
|
|
137
137
|
```bash
|
|
@@ -139,7 +139,7 @@ R - Retrospectives: Continuous learning from experience
|
|
|
139
139
|
# After: Rebase-on-master with force-with-lease for safety
|
|
140
140
|
```
|
|
141
141
|
|
|
142
|
-
#### ๐ **Systematic Debugging Patterns**
|
|
142
|
+
#### ๐ **Systematic Debugging Patterns**
|
|
143
143
|
**Problem**: Agents struggle with complex debugging and repeat the same mistakes
|
|
144
144
|
**Solution**: Structured debugging methodology with evidence collection and pattern recognition
|
|
145
145
|
```bash
|
|
@@ -147,7 +147,7 @@ R - Retrospectives: Continuous learning from experience
|
|
|
147
147
|
# After: Systematic approach with documented patterns and regression tests
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
-
#### ๐ **Package Scripts & Output Visibility**
|
|
150
|
+
#### ๐ **Package Scripts & Output Visibility**
|
|
151
151
|
**Problem**: Long-running tasks hang agents and provide no visibility into progress
|
|
152
152
|
**Solution**: Background execution with log files and timeout management
|
|
153
153
|
```bash
|
|
@@ -217,42 +217,6 @@ R - Retrospectives: Continuous learning from experience
|
|
|
217
217
|
|
|
218
218
|
## ๐๏ธ **Enterprise-Grade Framework Structure**
|
|
219
219
|
|
|
220
|
-
```
|
|
221
|
-
FRAIM/
|
|
222
|
-
โโโ ๐ง .ai-agents/rules/ # Guardrails - The "HR Handbook" for AI agents
|
|
223
|
-
โ โโโ integrity-and-test-ethics.md # Prevents "fake it till you make it"
|
|
224
|
-
โ โโโ agent-testing-guidelines.md # Ensures real validation, not claims
|
|
225
|
-
โ โโโ communication.md # Clear accountability and progress
|
|
226
|
-
โ โโโ architecture.md # Prevents technical debt
|
|
227
|
-
โ โโโ spike-first-development.md # Validates before building
|
|
228
|
-
โ โโโ continuous-learning.md # Learns from mistakes
|
|
229
|
-
โ โโโ simplicity.md # Prevents over-engineering
|
|
230
|
-
โ โโโ git-safe-commands.md # Prevents agent hangs on Git commands
|
|
231
|
-
โ โโโ merge-requirements.md # Safe branch management and rebasing
|
|
232
|
-
โ โโโ successful-debugging-patterns.md # Systematic debugging approach
|
|
233
|
-
โ โโโ local-development.md # Local development best practices
|
|
234
|
-
โ โโโ pr-workflow-completeness.md # PR workflow validation
|
|
235
|
-
โ โโโ software-development-lifecycle.md # Full SDLC integration
|
|
236
|
-
โ
|
|
237
|
-
โโโ ๐ .ai-agents/workflows/ # Process - The "Project Management Office"
|
|
238
|
-
โ โโโ spec.md # Specification and requirements phase
|
|
239
|
-
โ โโโ design.md # Structured design phase
|
|
240
|
-
โ โโโ implement.md # Implementation with validation
|
|
241
|
-
โ โโโ test.md # Comprehensive testing
|
|
242
|
-
โ โโโ resolve.md # Issue resolution workflow
|
|
243
|
-
โ โโโ retrospect.md # Learning and improvement
|
|
244
|
-
โ
|
|
245
|
-
โโโ ๐ .ai-agents/templates/ # Human Interfaces - The "Standard Operating Procedures"
|
|
246
|
-
โ โโโ evidence/ # Proof of work templates
|
|
247
|
-
โ โโโ retrospective/ # Learning capture templates
|
|
248
|
-
โ โโโ specs/ # Specification templates
|
|
249
|
-
โ
|
|
250
|
-
โโโ ๐ ๏ธ Scripts & Automation # Determinism - The "DevOps Pipeline"
|
|
251
|
-
โโโ prep-issue.sh # Issue preparation
|
|
252
|
-
โโโ exec-with-timeout.ts # Command execution with timeout & output visibility
|
|
253
|
-
โโโ cleanup-branch.ts # Branch management
|
|
254
|
-
```
|
|
255
|
-
|
|
256
220
|
## ๐ **Get Started in 60 Seconds**
|
|
257
221
|
|
|
258
222
|
### **โ ๏ธ Prerequisites**
|
|
@@ -293,63 +257,6 @@ fraim sync # Sync latest workflows and rules
|
|
|
293
257
|
|
|
294
258
|
**๐ก Pro Tip**: Use `fraim add-ide` when you install a new IDE after initial setup. It reuses your existing FRAIM and GitHub keys, making it much faster than running full setup again.
|
|
295
259
|
|
|
296
|
-
### **๐ง Customize for Your Project**
|
|
297
|
-
|
|
298
|
-
After installation, customize these files for your specific project:
|
|
299
|
-
|
|
300
|
-
#### **1. Architecture Rules** (`.ai-agents/rules/architecture.md`)
|
|
301
|
-
- **Purpose**: Define your system's architectural patterns and boundaries
|
|
302
|
-
- **Customize**: Replace generic examples with your specific architecture patterns
|
|
303
|
-
- **Example**: Add your database patterns, API structures, service boundaries
|
|
304
|
-
|
|
305
|
-
#### **2. Branch Cleanup Script** (`.ai-agents/scripts/cleanup-branch.ts`)
|
|
306
|
-
- **Purpose**: Project-specific cleanup when branches are deleted
|
|
307
|
-
- **Customize**: Add your cleanup logic in the `insertYourCodeHere()` method
|
|
308
|
-
- **Example**: Database cleanup, cache invalidation, temporary file removal
|
|
309
|
-
|
|
310
|
-
#### **3. Package Scripts** (`sample_package.json` โ `package.json`)
|
|
311
|
-
- **Purpose**: Testing and build scripts for your project
|
|
312
|
-
- **Adopt**: Copy relevant scripts from `sample_package.json` into your main `package.json`
|
|
313
|
-
- **Customize**: Update test commands, build processes, and framework-specific commands
|
|
314
|
-
- **Example**: Replace `baml-cli generate` with your framework's generate command
|
|
315
|
-
|
|
316
|
-
#### **4. Test Utilities** (`test-utils.ts` โ your project)
|
|
317
|
-
- **Purpose**: Generic test framework with tagging system
|
|
318
|
-
- **Adopt**: Copy `test-utils.ts` into your project and import in your test files
|
|
319
|
-
- **Customize**: Extend `BaseTestCase` interface for your specific test needs
|
|
320
|
-
- **Example**: Create domain-specific test cases using the tagging system
|
|
321
|
-
|
|
322
|
-
#### **5. Test Structure** (`examples/simple-webapp/example-test.ts`)
|
|
323
|
-
- **Purpose**: Example test cases with proper tagging
|
|
324
|
-
- **Adopt**: Use as a template for your project's test structure
|
|
325
|
-
- **Customize**: Replace with your project's test cases and domain-specific tags
|
|
326
|
-
- **Example**: Add your specific test scenarios and validation patterns
|
|
327
|
-
|
|
328
|
-
## ๐ฏ **The Transformation: From Developer to AI Manager**
|
|
329
|
-
|
|
330
|
-
### **Phase 1: Setup (5 minutes)**
|
|
331
|
-
```bash
|
|
332
|
-
npx fraim-framework init
|
|
333
|
-
# โ
Repository configured with AI management rules
|
|
334
|
-
# โ
Agents assigned to specific roles (Design, Implementation, Testing)
|
|
335
|
-
# โ
Workflows and templates installed
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
### **Phase 2: Issue Management (30 seconds per issue)**
|
|
339
|
-
```bash
|
|
340
|
-
gh issue create --title "Add user authentication" --label "ai-agent:cursor"
|
|
341
|
-
# โ
Git issue is centralized coordination point
|
|
342
|
-
# โ
Agent assignment handled
|
|
343
|
-
# โ
Ready for work
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
### **Phase 3: Orchestrated Development**
|
|
347
|
-
```bash
|
|
348
|
-
.ai-agents/scripts/prep-issue.sh #issue_number
|
|
349
|
-
# โ
Local clone and new branch created
|
|
350
|
-
# โ
Coding agent initiated
|
|
351
|
-
# โ
Tell coding agent which phase it should proceed with
|
|
352
|
-
```
|
|
353
260
|
|
|
354
261
|
## ๐ **Why FRAIM is the Future**
|
|
355
262
|
|
|
@@ -414,4 +321,4 @@ Stop fighting with AI agents. Start orchestrating them.
|
|
|
414
321
|
[](https://github.com/mathursrus/FRAIM/stargazers)
|
|
415
322
|
[](https://opensource.org/licenses/MIT)
|
|
416
323
|
|
|
417
|
-
</div>
|
|
324
|
+
</div>
|
package/bin/fraim-mcp.js
CHANGED
|
@@ -12,6 +12,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
12
12
|
const os_1 = __importDefault(require("os"));
|
|
13
13
|
const ide_detector_1 = require("../setup/ide-detector");
|
|
14
14
|
const mcp_config_generator_1 = require("../setup/mcp-config-generator");
|
|
15
|
+
const codex_local_config_1 = require("../setup/codex-local-config");
|
|
15
16
|
const loadGlobalConfig = () => {
|
|
16
17
|
const globalConfigPath = path_1.default.join(os_1.default.homedir(), '.fraim', 'config.json');
|
|
17
18
|
if (!fs_1.default.existsSync(globalConfigPath)) {
|
|
@@ -129,26 +130,18 @@ const configureIDEMCP = async (ide, fraimKey, githubToken) => {
|
|
|
129
130
|
console.log(chalk_1.default.gray(` ๐ Found existing TOML config`));
|
|
130
131
|
}
|
|
131
132
|
const newTomlContent = (0, mcp_config_generator_1.generateMCPConfig)(ide.configType, fraimKey, githubToken);
|
|
132
|
-
let finalContent = existingTomlContent;
|
|
133
133
|
const serversToAdd = ['fraim', 'git', 'github', 'playwright'];
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const serverRegex = new RegExp(`\\[mcp_servers\\.${server}\\][\\s\\S]*?(?=\\[mcp_servers\\.|$)`, 'g');
|
|
138
|
-
const serverMatch = newTomlContent.match(serverRegex);
|
|
139
|
-
if (serverMatch) {
|
|
140
|
-
finalContent += '\n' + serverMatch[0].trim() + '\n';
|
|
141
|
-
addedServers.push(server);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
else {
|
|
145
|
-
console.log(chalk_1.default.gray(` โญ๏ธ Skipped ${server} (already exists)`));
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
fs_1.default.writeFileSync(configPath, finalContent);
|
|
149
|
-
addedServers.forEach(server => {
|
|
134
|
+
const mergeResult = (0, mcp_config_generator_1.mergeTomlMCPServers)(existingTomlContent, newTomlContent, serversToAdd);
|
|
135
|
+
fs_1.default.writeFileSync(configPath, mergeResult.content);
|
|
136
|
+
mergeResult.addedServers.forEach(server => {
|
|
150
137
|
console.log(chalk_1.default.green(` โ
Added ${server} MCP server`));
|
|
151
138
|
});
|
|
139
|
+
mergeResult.replacedServers.forEach(server => {
|
|
140
|
+
console.log(chalk_1.default.green(` โ
Updated ${server} MCP server`));
|
|
141
|
+
});
|
|
142
|
+
mergeResult.skippedServers.forEach(server => {
|
|
143
|
+
console.log(chalk_1.default.gray(` โญ๏ธ Skipped ${server} (already configured or not requested)`));
|
|
144
|
+
});
|
|
152
145
|
}
|
|
153
146
|
else {
|
|
154
147
|
// Handle JSON format
|
|
@@ -183,6 +176,11 @@ const configureIDEMCP = async (ide, fraimKey, githubToken) => {
|
|
|
183
176
|
});
|
|
184
177
|
}
|
|
185
178
|
console.log(chalk_1.default.green(`โ
Updated ${configPath}`));
|
|
179
|
+
if (ide.configType === 'codex') {
|
|
180
|
+
const localResult = (0, codex_local_config_1.ensureCodexLocalConfig)(process.cwd());
|
|
181
|
+
const status = localResult.created ? 'Created' : localResult.updated ? 'Updated' : 'Verified';
|
|
182
|
+
console.log(chalk_1.default.green(` โ
${status} local Codex config: ${localResult.path}`));
|
|
183
|
+
}
|
|
186
184
|
};
|
|
187
185
|
const listSupportedIDEs = () => {
|
|
188
186
|
const allIDEs = (0, ide_detector_1.getAllSupportedIDEs)();
|
|
@@ -12,6 +12,8 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
12
12
|
const sync_1 = require("./sync");
|
|
13
13
|
const platform_detection_1 = require("../utils/platform-detection");
|
|
14
14
|
const version_utils_1 = require("../utils/version-utils");
|
|
15
|
+
const ide_detector_1 = require("../setup/ide-detector");
|
|
16
|
+
const codex_local_config_1 = require("../setup/codex-local-config");
|
|
15
17
|
const checkGlobalSetup = () => {
|
|
16
18
|
const fraimUserDir = process.env.FRAIM_USER_DIR || path_1.default.join(os_1.default.homedir(), '.fraim');
|
|
17
19
|
const globalConfigPath = path_1.default.join(fraimUserDir, 'config.json');
|
|
@@ -22,120 +24,111 @@ const checkGlobalSetup = () => {
|
|
|
22
24
|
const config = JSON.parse(fs_1.default.readFileSync(globalConfigPath, 'utf8'));
|
|
23
25
|
return {
|
|
24
26
|
exists: true,
|
|
25
|
-
mode: config.mode || 'integrated',
|
|
27
|
+
mode: config.mode || 'integrated',
|
|
26
28
|
tokens: config.tokens || {}
|
|
27
29
|
};
|
|
28
30
|
}
|
|
29
|
-
catch
|
|
31
|
+
catch {
|
|
30
32
|
return { exists: true, mode: 'integrated', tokens: {} };
|
|
31
33
|
}
|
|
32
34
|
};
|
|
33
35
|
const runInitProject = async () => {
|
|
34
|
-
console.log(chalk_1.default.blue('
|
|
35
|
-
// Check if global setup exists
|
|
36
|
+
console.log(chalk_1.default.blue('Initializing FRAIM project...'));
|
|
36
37
|
const globalSetup = checkGlobalSetup();
|
|
37
38
|
if (!globalSetup.exists) {
|
|
38
|
-
console.log(chalk_1.default.red('
|
|
39
|
+
console.log(chalk_1.default.red('Global FRAIM setup not found.'));
|
|
39
40
|
console.log(chalk_1.default.yellow('Please run global setup first:'));
|
|
40
41
|
console.log(chalk_1.default.cyan(' fraim setup'));
|
|
41
42
|
process.exit(1);
|
|
42
43
|
}
|
|
43
|
-
const mode = globalSetup.mode;
|
|
44
|
-
const tokens = globalSetup.tokens || {};
|
|
45
|
-
console.log(chalk_1.default.gray(` Mode: ${mode === 'conversational' ? 'Conversational' : 'Integrated'} (from global config)`));
|
|
46
44
|
const projectRoot = process.cwd();
|
|
47
45
|
const fraimDir = path_1.default.join(projectRoot, '.fraim');
|
|
48
46
|
const configPath = path_1.default.join(fraimDir, 'config.json');
|
|
49
47
|
if (!fs_1.default.existsSync(fraimDir)) {
|
|
50
48
|
fs_1.default.mkdirSync(fraimDir, { recursive: true });
|
|
51
|
-
console.log(chalk_1.default.green('
|
|
49
|
+
console.log(chalk_1.default.green('Created .fraim directory'));
|
|
52
50
|
}
|
|
53
51
|
else {
|
|
54
|
-
console.log(chalk_1.default.yellow('
|
|
52
|
+
console.log(chalk_1.default.yellow('.fraim directory already exists'));
|
|
55
53
|
}
|
|
56
54
|
if (!fs_1.default.existsSync(configPath)) {
|
|
55
|
+
const projectName = path_1.default.basename(projectRoot);
|
|
56
|
+
const preferredMode = globalSetup.mode || 'integrated';
|
|
57
57
|
let config;
|
|
58
|
-
if (
|
|
59
|
-
// Conversational mode - no platform integration
|
|
60
|
-
const projectName = path_1.default.basename(projectRoot);
|
|
58
|
+
if (preferredMode === 'conversational') {
|
|
61
59
|
config = {
|
|
62
60
|
version: (0, version_utils_1.getFraimVersion)(),
|
|
63
61
|
project: {
|
|
64
62
|
name: projectName
|
|
65
63
|
},
|
|
66
|
-
customizations: {
|
|
67
|
-
workflowsPath: '.fraim/workflows'
|
|
68
|
-
}
|
|
64
|
+
customizations: {}
|
|
69
65
|
};
|
|
70
|
-
console.log(chalk_1.default.blue('
|
|
66
|
+
console.log(chalk_1.default.blue(' conversational mode: no platform integration'));
|
|
71
67
|
console.log(chalk_1.default.gray(` Project: ${projectName}`));
|
|
72
68
|
}
|
|
73
69
|
else {
|
|
74
|
-
// Integrated mode - try to detect platform
|
|
75
70
|
const detection = (0, platform_detection_1.detectPlatformFromGit)();
|
|
76
71
|
if (detection.provider !== 'unknown' && detection.repository) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
72
|
+
const issueTracking = detection.provider === 'github'
|
|
73
|
+
? {
|
|
74
|
+
provider: 'github',
|
|
75
|
+
owner: detection.repository.owner,
|
|
76
|
+
name: detection.repository.name
|
|
77
|
+
}
|
|
78
|
+
: {
|
|
79
|
+
provider: 'ado',
|
|
80
|
+
organization: detection.repository.organization,
|
|
81
|
+
project: detection.repository.project,
|
|
82
|
+
name: detection.repository.name
|
|
83
|
+
};
|
|
85
84
|
config = {
|
|
86
85
|
version: (0, version_utils_1.getFraimVersion)(),
|
|
87
86
|
project: {
|
|
88
|
-
name: detection.repository.name
|
|
87
|
+
name: detection.repository.name || projectName
|
|
89
88
|
},
|
|
90
89
|
repository: detection.repository,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
90
|
+
issueTracking,
|
|
91
|
+
customizations: {}
|
|
94
92
|
};
|
|
95
93
|
console.log(chalk_1.default.blue(` Platform: ${detection.provider.toUpperCase()}`));
|
|
96
94
|
if (detection.provider === 'github') {
|
|
97
95
|
console.log(chalk_1.default.gray(` Repository: ${detection.repository.owner}/${detection.repository.name}`));
|
|
98
|
-
console.log(chalk_1.default.gray(` Token: ${hasToken ? 'โ Configured' : 'โ Missing'}`));
|
|
99
96
|
}
|
|
100
97
|
else if (detection.provider === 'ado') {
|
|
101
98
|
console.log(chalk_1.default.gray(` Organization: ${detection.repository.organization}`));
|
|
102
99
|
console.log(chalk_1.default.gray(` Project: ${detection.repository.project}`));
|
|
103
100
|
console.log(chalk_1.default.gray(` Repository: ${detection.repository.name}`));
|
|
104
|
-
console.log(chalk_1.default.gray(` Token: ${hasToken ? 'โ Configured' : 'โ Missing'}`));
|
|
105
101
|
}
|
|
106
102
|
}
|
|
107
103
|
else {
|
|
108
|
-
// No git remote detected - warn user and fallback to conversational-style config
|
|
109
|
-
console.log(chalk_1.default.yellow(' โ ๏ธ No git remote detected'));
|
|
110
|
-
console.log(chalk_1.default.yellow(' Integrated mode requires a git remote for platform features.'));
|
|
111
|
-
console.log(chalk_1.default.gray(' Falling back to conversational mode configuration...'));
|
|
112
|
-
const repoName = path_1.default.basename(projectRoot);
|
|
113
104
|
config = {
|
|
114
105
|
version: (0, version_utils_1.getFraimVersion)(),
|
|
115
106
|
project: {
|
|
116
|
-
name:
|
|
107
|
+
name: projectName
|
|
117
108
|
},
|
|
118
|
-
customizations: {
|
|
119
|
-
workflowsPath: '.fraim/workflows'
|
|
120
|
-
}
|
|
109
|
+
customizations: {}
|
|
121
110
|
};
|
|
122
|
-
console.log(chalk_1.default.
|
|
111
|
+
console.log(chalk_1.default.yellow(' No git remote detected. Falling back to conversational mode.'));
|
|
123
112
|
}
|
|
124
113
|
}
|
|
125
114
|
fs_1.default.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
126
|
-
console.log(chalk_1.default.green('
|
|
115
|
+
console.log(chalk_1.default.green('Created .fraim/config.json'));
|
|
127
116
|
}
|
|
128
|
-
|
|
129
|
-
['workflows'].forEach(dir => {
|
|
117
|
+
['workflows'].forEach((dir) => {
|
|
130
118
|
const dirPath = path_1.default.join(fraimDir, dir);
|
|
131
119
|
if (!fs_1.default.existsSync(dirPath)) {
|
|
132
120
|
fs_1.default.mkdirSync(dirPath, { recursive: true });
|
|
133
|
-
console.log(chalk_1.default.green(
|
|
121
|
+
console.log(chalk_1.default.green(`Created .fraim/${dir}`));
|
|
134
122
|
}
|
|
135
123
|
});
|
|
136
|
-
// Sync workflows from registry
|
|
137
124
|
await (0, sync_1.runSync)({});
|
|
138
|
-
|
|
125
|
+
const codexAvailable = (0, ide_detector_1.detectInstalledIDEs)().some((ide) => ide.configType === 'codex');
|
|
126
|
+
if (codexAvailable) {
|
|
127
|
+
const codexLocalResult = (0, codex_local_config_1.ensureCodexLocalConfig)(projectRoot);
|
|
128
|
+
const status = codexLocalResult.created ? 'Created' : codexLocalResult.updated ? 'Updated' : 'Verified';
|
|
129
|
+
console.log(chalk_1.default.green(`${status} project Codex config at ${codexLocalResult.path}`));
|
|
130
|
+
}
|
|
131
|
+
console.log(chalk_1.default.green('\nFRAIM project initialized!'));
|
|
139
132
|
console.log(chalk_1.default.cyan('Try: Ask your AI agent "list fraim workflows"'));
|
|
140
133
|
};
|
|
141
134
|
exports.runInitProject = runInitProject;
|
|
@@ -108,7 +108,11 @@ exports.overrideCommand = new commander_1.Command('override')
|
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
};
|
|
111
|
-
await axios_1.default.post(`${serverUrl}/mcp`, connectRequest, { headers, timeout: 30000 });
|
|
111
|
+
const connectResponse = await axios_1.default.post(`${serverUrl}/mcp`, connectRequest, { headers, timeout: 30000 });
|
|
112
|
+
const sessionId = connectResponse.data?.result?.sessionId;
|
|
113
|
+
if (typeof sessionId !== 'string' || sessionId.trim().length === 0) {
|
|
114
|
+
throw new Error('fraim_connect did not return a sessionId');
|
|
115
|
+
}
|
|
112
116
|
// Now determine MCP tool and arguments based on path
|
|
113
117
|
let toolName;
|
|
114
118
|
let toolArgs;
|
|
@@ -132,9 +136,15 @@ exports.overrideCommand = new commander_1.Command('override')
|
|
|
132
136
|
method: 'tools/call',
|
|
133
137
|
params: {
|
|
134
138
|
name: toolName,
|
|
139
|
+
sessionId: sessionId.trim(),
|
|
135
140
|
arguments: toolArgs
|
|
136
141
|
}
|
|
137
142
|
};
|
|
143
|
+
// Mirror sessionId in arguments for compatibility with both server and proxy paths.
|
|
144
|
+
mcpRequest.params.arguments = {
|
|
145
|
+
...mcpRequest.params.arguments,
|
|
146
|
+
sessionId: sessionId.trim()
|
|
147
|
+
};
|
|
138
148
|
const response = await axios_1.default.post(`${serverUrl}/mcp`, mcpRequest, {
|
|
139
149
|
headers,
|
|
140
150
|
timeout: 30000
|
|
@@ -11,6 +11,7 @@ const prompts_1 = __importDefault(require("prompts"));
|
|
|
11
11
|
const ide_detector_1 = require("./ide-detector");
|
|
12
12
|
const mcp_config_generator_1 = require("./mcp-config-generator");
|
|
13
13
|
const token_validator_1 = require("./token-validator");
|
|
14
|
+
const codex_local_config_1 = require("./codex-local-config");
|
|
14
15
|
const promptForIDESelection = async (detectedIDEs, githubToken) => {
|
|
15
16
|
console.log(chalk_1.default.green(`โ
Found ${detectedIDEs.length} IDEs that can be configured with FRAIM:\n`));
|
|
16
17
|
detectedIDEs.forEach((ide, index) => {
|
|
@@ -228,28 +229,18 @@ const configureIDEMCP = async (ide, fraimKey, githubToken) => {
|
|
|
228
229
|
console.log(chalk_1.default.gray(` ๐ Found existing TOML config`));
|
|
229
230
|
}
|
|
230
231
|
const newTomlContent = (0, mcp_config_generator_1.generateMCPConfig)(ide.configType, fraimKey, githubToken);
|
|
231
|
-
// For TOML, we'll append new servers if they don't exist
|
|
232
|
-
let finalContent = existingTomlContent;
|
|
233
232
|
const serversToAdd = ['fraim', 'git', 'github', 'playwright'];
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
// Extract this server's config from the new content
|
|
238
|
-
const serverRegex = new RegExp(`\\[mcp_servers\\.${server}\\][\\s\\S]*?(?=\\[mcp_servers\\.|$)`, 'g');
|
|
239
|
-
const serverMatch = newTomlContent.match(serverRegex);
|
|
240
|
-
if (serverMatch) {
|
|
241
|
-
finalContent += '\n' + serverMatch[0].trim() + '\n';
|
|
242
|
-
addedServers.push(server);
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
else {
|
|
246
|
-
console.log(chalk_1.default.gray(` โญ๏ธ Skipped ${server} (already exists)`));
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
fs_1.default.writeFileSync(configPath, finalContent);
|
|
250
|
-
addedServers.forEach(server => {
|
|
233
|
+
const mergeResult = (0, mcp_config_generator_1.mergeTomlMCPServers)(existingTomlContent, newTomlContent, serversToAdd);
|
|
234
|
+
fs_1.default.writeFileSync(configPath, mergeResult.content);
|
|
235
|
+
mergeResult.addedServers.forEach(server => {
|
|
251
236
|
console.log(chalk_1.default.green(` โ
Added ${server} MCP server`));
|
|
252
237
|
});
|
|
238
|
+
mergeResult.replacedServers.forEach(server => {
|
|
239
|
+
console.log(chalk_1.default.green(` โ
Updated ${server} MCP server`));
|
|
240
|
+
});
|
|
241
|
+
mergeResult.skippedServers.forEach(server => {
|
|
242
|
+
console.log(chalk_1.default.gray(` โญ๏ธ Skipped ${server} (already configured or not requested)`));
|
|
243
|
+
});
|
|
253
244
|
}
|
|
254
245
|
else {
|
|
255
246
|
// For JSON configs - intelligent merging
|
|
@@ -283,6 +274,11 @@ const configureIDEMCP = async (ide, fraimKey, githubToken) => {
|
|
|
283
274
|
});
|
|
284
275
|
}
|
|
285
276
|
console.log(chalk_1.default.green(`โ
Updated ${configPath}`));
|
|
277
|
+
if (ide.configType === 'codex') {
|
|
278
|
+
const localResult = (0, codex_local_config_1.ensureCodexLocalConfig)(process.cwd());
|
|
279
|
+
const status = localResult.created ? 'Created' : localResult.updated ? 'Updated' : 'Verified';
|
|
280
|
+
console.log(chalk_1.default.green(` โ
${status} local Codex config: ${localResult.path}`));
|
|
281
|
+
}
|
|
286
282
|
};
|
|
287
283
|
const autoConfigureMCP = async (fraimKey, githubToken, selectedIDEs) => {
|
|
288
284
|
const detectedIDEs = (0, ide_detector_1.detectInstalledIDEs)();
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ensureCodexLocalConfig = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const mcp_config_generator_1 = require("./mcp-config-generator");
|
|
10
|
+
const escapeTomlString = (value) => value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
11
|
+
const buildFraimCwdBlock = (projectRoot) => `
|
|
12
|
+
[mcp_servers.fraim]
|
|
13
|
+
cwd = "${escapeTomlString(projectRoot)}"
|
|
14
|
+
`;
|
|
15
|
+
const ensureCodexLocalConfig = (projectRoot) => {
|
|
16
|
+
const codexDir = path_1.default.join(projectRoot, '.codex');
|
|
17
|
+
const codexConfigPath = path_1.default.join(codexDir, 'config.toml');
|
|
18
|
+
if (!fs_1.default.existsSync(codexDir)) {
|
|
19
|
+
fs_1.default.mkdirSync(codexDir, { recursive: true });
|
|
20
|
+
}
|
|
21
|
+
const hadExistingFile = fs_1.default.existsSync(codexConfigPath);
|
|
22
|
+
const existingContent = hadExistingFile ? fs_1.default.readFileSync(codexConfigPath, 'utf8') : '';
|
|
23
|
+
const generatedContent = buildFraimCwdBlock(projectRoot);
|
|
24
|
+
const mergeResult = (0, mcp_config_generator_1.mergeTomlMCPServers)(existingContent, generatedContent, ['fraim']);
|
|
25
|
+
const normalizedExisting = existingContent.replace(/\r\n/g, '\n');
|
|
26
|
+
const normalizedMerged = mergeResult.content.replace(/\r\n/g, '\n');
|
|
27
|
+
const shouldWrite = !hadExistingFile || normalizedExisting !== normalizedMerged;
|
|
28
|
+
if (shouldWrite) {
|
|
29
|
+
fs_1.default.writeFileSync(codexConfigPath, mergeResult.content);
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
path: codexConfigPath,
|
|
33
|
+
created: !hadExistingFile,
|
|
34
|
+
updated: shouldWrite && hadExistingFile
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
exports.ensureCodexLocalConfig = ensureCodexLocalConfig;
|