fraim 2.0.100

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.
Files changed (70) hide show
  1. package/README.md +445 -0
  2. package/bin/fraim.js +23 -0
  3. package/dist/src/cli/api/get-provider-client.js +41 -0
  4. package/dist/src/cli/api/provider-client.js +107 -0
  5. package/dist/src/cli/commands/add-ide.js +430 -0
  6. package/dist/src/cli/commands/add-provider.js +233 -0
  7. package/dist/src/cli/commands/doctor.js +149 -0
  8. package/dist/src/cli/commands/init-project.js +301 -0
  9. package/dist/src/cli/commands/list-overridable.js +184 -0
  10. package/dist/src/cli/commands/list.js +57 -0
  11. package/dist/src/cli/commands/login.js +84 -0
  12. package/dist/src/cli/commands/mcp.js +15 -0
  13. package/dist/src/cli/commands/migrate-project-fraim.js +42 -0
  14. package/dist/src/cli/commands/override.js +177 -0
  15. package/dist/src/cli/commands/setup.js +651 -0
  16. package/dist/src/cli/commands/sync.js +162 -0
  17. package/dist/src/cli/commands/test-mcp.js +171 -0
  18. package/dist/src/cli/doctor/check-runner.js +199 -0
  19. package/dist/src/cli/doctor/checks/global-setup-checks.js +220 -0
  20. package/dist/src/cli/doctor/checks/ide-config-checks.js +250 -0
  21. package/dist/src/cli/doctor/checks/mcp-connectivity-checks.js +381 -0
  22. package/dist/src/cli/doctor/checks/project-setup-checks.js +282 -0
  23. package/dist/src/cli/doctor/checks/scripts-checks.js +157 -0
  24. package/dist/src/cli/doctor/checks/workflow-checks.js +251 -0
  25. package/dist/src/cli/doctor/reporters/console-reporter.js +96 -0
  26. package/dist/src/cli/doctor/reporters/json-reporter.js +11 -0
  27. package/dist/src/cli/doctor/types.js +6 -0
  28. package/dist/src/cli/fraim.js +100 -0
  29. package/dist/src/cli/internal/device-flow-service.js +83 -0
  30. package/dist/src/cli/mcp/ide-formats.js +243 -0
  31. package/dist/src/cli/mcp/mcp-server-builder.js +48 -0
  32. package/dist/src/cli/mcp/mcp-server-registry.js +160 -0
  33. package/dist/src/cli/mcp/types.js +3 -0
  34. package/dist/src/cli/providers/local-provider-registry.js +166 -0
  35. package/dist/src/cli/providers/provider-registry.js +230 -0
  36. package/dist/src/cli/setup/auto-mcp-setup.js +331 -0
  37. package/dist/src/cli/setup/codex-local-config.js +37 -0
  38. package/dist/src/cli/setup/first-run.js +242 -0
  39. package/dist/src/cli/setup/ide-detector.js +179 -0
  40. package/dist/src/cli/setup/mcp-config-generator.js +192 -0
  41. package/dist/src/cli/setup/provider-prompts.js +339 -0
  42. package/dist/src/cli/utils/agent-adapters.js +126 -0
  43. package/dist/src/cli/utils/digest-utils.js +47 -0
  44. package/dist/src/cli/utils/fraim-gitignore.js +40 -0
  45. package/dist/src/cli/utils/platform-detection.js +258 -0
  46. package/dist/src/cli/utils/project-bootstrap.js +93 -0
  47. package/dist/src/cli/utils/remote-sync.js +315 -0
  48. package/dist/src/cli/utils/script-sync-utils.js +221 -0
  49. package/dist/src/cli/utils/version-utils.js +32 -0
  50. package/dist/src/core/ai-mentor.js +230 -0
  51. package/dist/src/core/config-loader.js +114 -0
  52. package/dist/src/core/config-writer.js +75 -0
  53. package/dist/src/core/types.js +23 -0
  54. package/dist/src/core/utils/git-utils.js +95 -0
  55. package/dist/src/core/utils/include-resolver.js +92 -0
  56. package/dist/src/core/utils/inheritance-parser.js +288 -0
  57. package/dist/src/core/utils/job-parser.js +176 -0
  58. package/dist/src/core/utils/local-registry-resolver.js +616 -0
  59. package/dist/src/core/utils/object-utils.js +11 -0
  60. package/dist/src/core/utils/project-fraim-migration.js +103 -0
  61. package/dist/src/core/utils/project-fraim-paths.js +38 -0
  62. package/dist/src/core/utils/provider-utils.js +18 -0
  63. package/dist/src/core/utils/server-startup.js +34 -0
  64. package/dist/src/core/utils/stub-generator.js +147 -0
  65. package/dist/src/core/utils/workflow-parser.js +174 -0
  66. package/dist/src/local-mcp-server/learning-context-builder.js +229 -0
  67. package/dist/src/local-mcp-server/stdio-server.js +1698 -0
  68. package/dist/src/local-mcp-server/usage-collector.js +264 -0
  69. package/index.js +85 -0
  70. package/package.json +139 -0
@@ -0,0 +1,220 @@
1
+ "use strict";
2
+ /**
3
+ * Global setup checks for FRAIM doctor command
4
+ * Validates global configuration and API keys
5
+ * Issue #144: Enhanced doctor command
6
+ */
7
+ var __importDefault = (this && this.__importDefault) || function (mod) {
8
+ return (mod && mod.__esModule) ? mod : { "default": mod };
9
+ };
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.getGlobalSetupChecks = getGlobalSetupChecks;
12
+ const fs_1 = __importDefault(require("fs"));
13
+ const path_1 = __importDefault(require("path"));
14
+ const os_1 = __importDefault(require("os"));
15
+ const getGlobalConfigPath = () => path_1.default.join(os_1.default.homedir(), '.fraim', 'config.json');
16
+ /**
17
+ * Check if global config exists
18
+ */
19
+ function checkGlobalConfigExists() {
20
+ return {
21
+ name: 'Global config exists',
22
+ category: 'globalSetup',
23
+ critical: true,
24
+ run: async () => {
25
+ if (fs_1.default.existsSync(getGlobalConfigPath())) {
26
+ return {
27
+ status: 'passed',
28
+ message: 'Global config exists',
29
+ details: { path: getGlobalConfigPath() }
30
+ };
31
+ }
32
+ return {
33
+ status: 'error',
34
+ message: 'Global config missing',
35
+ suggestion: 'Run fraim setup to create global configuration',
36
+ command: 'fraim setup'
37
+ };
38
+ }
39
+ };
40
+ }
41
+ /**
42
+ * Check if mode is valid
43
+ */
44
+ function checkModeValid() {
45
+ return {
46
+ name: 'Mode valid',
47
+ category: 'globalSetup',
48
+ critical: false,
49
+ run: async () => {
50
+ try {
51
+ if (!fs_1.default.existsSync(getGlobalConfigPath())) {
52
+ return {
53
+ status: 'error',
54
+ message: 'Cannot check mode - global config missing'
55
+ };
56
+ }
57
+ const config = JSON.parse(fs_1.default.readFileSync(getGlobalConfigPath(), 'utf8'));
58
+ const mode = config.mode || 'conversational';
59
+ const validModes = ['conversational', 'integrated', 'split'];
60
+ if (validModes.includes(mode)) {
61
+ return {
62
+ status: 'passed',
63
+ message: `Mode: ${mode}`,
64
+ details: { mode }
65
+ };
66
+ }
67
+ return {
68
+ status: 'error',
69
+ message: `Invalid mode: ${mode}`,
70
+ suggestion: 'Mode must be conversational, integrated, or split',
71
+ details: { mode, validModes }
72
+ };
73
+ }
74
+ catch (error) {
75
+ return {
76
+ status: 'error',
77
+ message: 'Failed to read mode from config',
78
+ details: { error: error.message }
79
+ };
80
+ }
81
+ }
82
+ };
83
+ }
84
+ /**
85
+ * Check if API key is configured
86
+ */
87
+ function checkApiKeyConfigured() {
88
+ return {
89
+ name: 'API key configured',
90
+ category: 'globalSetup',
91
+ critical: false,
92
+ run: async () => {
93
+ try {
94
+ if (!fs_1.default.existsSync(getGlobalConfigPath())) {
95
+ return {
96
+ status: 'error',
97
+ message: 'Cannot check API key - global config missing'
98
+ };
99
+ }
100
+ const config = JSON.parse(fs_1.default.readFileSync(getGlobalConfigPath(), 'utf8'));
101
+ if (config.apiKey) {
102
+ const maskedKey = config.apiKey.substring(0, 10) + '...';
103
+ return {
104
+ status: 'passed',
105
+ message: `API key configured (${maskedKey})`,
106
+ details: { keyPrefix: config.apiKey.substring(0, 10) }
107
+ };
108
+ }
109
+ return {
110
+ status: 'warning',
111
+ message: 'API key not configured',
112
+ suggestion: 'Add apiKey to global config for remote features',
113
+ details: { configPath: getGlobalConfigPath() }
114
+ };
115
+ }
116
+ catch (error) {
117
+ return {
118
+ status: 'error',
119
+ message: 'Failed to read API key from config',
120
+ details: { error: error.message }
121
+ };
122
+ }
123
+ }
124
+ };
125
+ }
126
+ /**
127
+ * Check if GitHub token is configured
128
+ */
129
+ function checkGitHubTokenConfigured() {
130
+ return {
131
+ name: 'GitHub token configured',
132
+ category: 'globalSetup',
133
+ critical: false,
134
+ run: async () => {
135
+ try {
136
+ if (!fs_1.default.existsSync(getGlobalConfigPath())) {
137
+ return {
138
+ status: 'error',
139
+ message: 'Cannot check GitHub token - global config missing'
140
+ };
141
+ }
142
+ const config = JSON.parse(fs_1.default.readFileSync(getGlobalConfigPath(), 'utf8'));
143
+ // Check if repository provider is GitHub
144
+ if (config.repository?.provider === 'github') {
145
+ // Token would be in IDE MCP configs, not global config
146
+ return {
147
+ status: 'passed',
148
+ message: 'GitHub provider configured',
149
+ details: { provider: 'github' }
150
+ };
151
+ }
152
+ return {
153
+ status: 'passed',
154
+ message: 'GitHub not configured (not required)',
155
+ details: { provider: config.repository?.provider || 'none' }
156
+ };
157
+ }
158
+ catch (error) {
159
+ return {
160
+ status: 'error',
161
+ message: 'Failed to check GitHub configuration',
162
+ details: { error: error.message }
163
+ };
164
+ }
165
+ }
166
+ };
167
+ }
168
+ /**
169
+ * Check if remote URL is configured (optional)
170
+ */
171
+ function checkRemoteUrlConfigured() {
172
+ return {
173
+ name: 'Remote URL configured',
174
+ category: 'globalSetup',
175
+ critical: false,
176
+ run: async () => {
177
+ try {
178
+ if (!fs_1.default.existsSync(getGlobalConfigPath())) {
179
+ return {
180
+ status: 'error',
181
+ message: 'Cannot check remote URL - global config missing'
182
+ };
183
+ }
184
+ const config = JSON.parse(fs_1.default.readFileSync(getGlobalConfigPath(), 'utf8'));
185
+ if (config.remoteUrl) {
186
+ return {
187
+ status: 'passed',
188
+ message: `Remote URL: ${config.remoteUrl}`,
189
+ details: { remoteUrl: config.remoteUrl }
190
+ };
191
+ }
192
+ // Remote URL is optional - just note it's not configured
193
+ return {
194
+ status: 'passed',
195
+ message: 'Remote URL not configured (optional)',
196
+ details: { configPath: getGlobalConfigPath(), optional: true }
197
+ };
198
+ }
199
+ catch (error) {
200
+ return {
201
+ status: 'error',
202
+ message: 'Failed to read remote URL from config',
203
+ details: { error: error.message }
204
+ };
205
+ }
206
+ }
207
+ };
208
+ }
209
+ /**
210
+ * Get all global setup checks
211
+ */
212
+ function getGlobalSetupChecks() {
213
+ return [
214
+ checkGlobalConfigExists(),
215
+ checkModeValid(),
216
+ checkApiKeyConfigured(),
217
+ checkGitHubTokenConfigured(),
218
+ checkRemoteUrlConfigured()
219
+ ];
220
+ }
@@ -0,0 +1,250 @@
1
+ "use strict";
2
+ /**
3
+ * IDE configuration checks for FRAIM doctor command
4
+ * Validates IDE installations and MCP configurations
5
+ * Issue #144: Enhanced doctor command
6
+ */
7
+ var __importDefault = (this && this.__importDefault) || function (mod) {
8
+ return (mod && mod.__esModule) ? mod : { "default": mod };
9
+ };
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.getIDEConfigChecks = getIDEConfigChecks;
12
+ const fs_1 = __importDefault(require("fs"));
13
+ const ide_detector_1 = require("../../setup/ide-detector");
14
+ /**
15
+ * Check if any IDEs are detected
16
+ */
17
+ function checkIDEsDetected() {
18
+ return {
19
+ name: 'IDEs detected',
20
+ category: 'ideConfiguration',
21
+ critical: false,
22
+ run: async () => {
23
+ const installedIDEs = (0, ide_detector_1.detectInstalledIDEs)();
24
+ if (installedIDEs.length > 0) {
25
+ const ideNames = installedIDEs.map(ide => ide.name).join(', ');
26
+ return {
27
+ status: 'passed',
28
+ message: `${installedIDEs.length} IDE(s) detected: ${ideNames}`,
29
+ details: {
30
+ count: installedIDEs.length,
31
+ ides: installedIDEs.map(ide => ide.name)
32
+ }
33
+ };
34
+ }
35
+ return {
36
+ status: 'warning',
37
+ message: 'No IDEs detected',
38
+ suggestion: 'Install Claude Desktop, Cursor, or another supported IDE',
39
+ details: { supportedIDEs: ['Claude Desktop', 'Cursor', 'Windsurf', 'VS Code', 'Zed', 'Codex'] }
40
+ };
41
+ }
42
+ };
43
+ }
44
+ /**
45
+ * Check if MCP configs exist for detected IDEs
46
+ */
47
+ function checkMCPConfigsExist() {
48
+ return {
49
+ name: 'MCP configs exist',
50
+ category: 'ideConfiguration',
51
+ critical: false,
52
+ run: async () => {
53
+ const installedIDEs = (0, ide_detector_1.detectInstalledIDEs)();
54
+ if (installedIDEs.length === 0) {
55
+ return {
56
+ status: 'warning',
57
+ message: 'No IDEs detected to check configs'
58
+ };
59
+ }
60
+ let existCount = 0;
61
+ let missingCount = 0;
62
+ const missing = [];
63
+ for (const ide of installedIDEs) {
64
+ const configPath = (0, ide_detector_1.expandPath)(ide.configPath);
65
+ if (fs_1.default.existsSync(configPath)) {
66
+ existCount++;
67
+ }
68
+ else {
69
+ missingCount++;
70
+ missing.push(ide.name);
71
+ }
72
+ }
73
+ if (missingCount === 0) {
74
+ return {
75
+ status: 'passed',
76
+ message: `MCP configs exist for all ${existCount} IDE(s)`,
77
+ details: { existCount }
78
+ };
79
+ }
80
+ if (existCount > 0) {
81
+ return {
82
+ status: 'warning',
83
+ message: `MCP configs missing for ${missingCount} IDE(s): ${missing.join(', ')}`,
84
+ suggestion: 'Run fraim add-ide to configure MCP servers',
85
+ command: 'fraim add-ide',
86
+ details: { existCount, missingCount, missing }
87
+ };
88
+ }
89
+ return {
90
+ status: 'error',
91
+ message: 'No MCP configs found',
92
+ suggestion: 'Run fraim add-ide to configure MCP servers',
93
+ command: 'fraim add-ide'
94
+ };
95
+ }
96
+ };
97
+ }
98
+ /**
99
+ * Check if MCP configs are valid JSON/TOML
100
+ */
101
+ function checkMCPConfigsValid() {
102
+ return {
103
+ name: 'MCP configs valid',
104
+ category: 'ideConfiguration',
105
+ critical: false,
106
+ run: async () => {
107
+ const installedIDEs = (0, ide_detector_1.detectInstalledIDEs)();
108
+ if (installedIDEs.length === 0) {
109
+ return {
110
+ status: 'warning',
111
+ message: 'No IDEs detected to validate configs'
112
+ };
113
+ }
114
+ let validCount = 0;
115
+ let invalidCount = 0;
116
+ const invalid = [];
117
+ for (const ide of installedIDEs) {
118
+ const configPath = (0, ide_detector_1.expandPath)(ide.configPath);
119
+ if (!fs_1.default.existsSync(configPath)) {
120
+ continue; // Skip missing configs
121
+ }
122
+ try {
123
+ if (ide.configFormat === 'json') {
124
+ JSON.parse(fs_1.default.readFileSync(configPath, 'utf8'));
125
+ validCount++;
126
+ }
127
+ else if (ide.configFormat === 'toml') {
128
+ // Basic TOML validation - just check if file is readable
129
+ fs_1.default.readFileSync(configPath, 'utf8');
130
+ validCount++;
131
+ }
132
+ }
133
+ catch (error) {
134
+ invalidCount++;
135
+ invalid.push(`${ide.name}: ${error.message}`);
136
+ }
137
+ }
138
+ if (invalidCount === 0 && validCount > 0) {
139
+ return {
140
+ status: 'passed',
141
+ message: `All ${validCount} MCP config(s) valid`,
142
+ details: { validCount }
143
+ };
144
+ }
145
+ if (invalidCount > 0) {
146
+ return {
147
+ status: 'error',
148
+ message: `${invalidCount} invalid MCP config(s)`,
149
+ suggestion: 'Fix syntax errors in MCP configuration files',
150
+ details: { invalid }
151
+ };
152
+ }
153
+ return {
154
+ status: 'warning',
155
+ message: 'No MCP configs to validate'
156
+ };
157
+ }
158
+ };
159
+ }
160
+ /**
161
+ * Check if FRAIM MCP server is configured in IDEs
162
+ */
163
+ function checkFraimServerConfigured() {
164
+ return {
165
+ name: 'FRAIM MCP server configured',
166
+ category: 'ideConfiguration',
167
+ critical: false,
168
+ run: async () => {
169
+ const installedIDEs = (0, ide_detector_1.detectInstalledIDEs)();
170
+ if (installedIDEs.length === 0) {
171
+ return {
172
+ status: 'warning',
173
+ message: 'No IDEs detected to check FRAIM server'
174
+ };
175
+ }
176
+ let configuredCount = 0;
177
+ let missingCount = 0;
178
+ const missing = [];
179
+ for (const ide of installedIDEs) {
180
+ const configPath = (0, ide_detector_1.expandPath)(ide.configPath);
181
+ if (!fs_1.default.existsSync(configPath)) {
182
+ continue;
183
+ }
184
+ try {
185
+ if (ide.configFormat === 'json') {
186
+ const config = JSON.parse(fs_1.default.readFileSync(configPath, 'utf8'));
187
+ let servers = config.mcpServers || {};
188
+ if (Object.keys(servers).length === 0 && config.servers) {
189
+ servers = config.servers;
190
+ }
191
+ if (servers['fraim']) {
192
+ configuredCount++;
193
+ }
194
+ else {
195
+ missingCount++;
196
+ missing.push(ide.name);
197
+ }
198
+ }
199
+ else if (ide.configFormat === 'toml') {
200
+ const toml = require('toml');
201
+ const content = fs_1.default.readFileSync(configPath, 'utf8');
202
+ const config = toml.parse(content);
203
+ const servers = config.mcp_servers || {};
204
+ if (servers['fraim']) {
205
+ configuredCount++;
206
+ }
207
+ else {
208
+ missingCount++;
209
+ missing.push(ide.name);
210
+ }
211
+ }
212
+ }
213
+ catch (error) {
214
+ // Config validation already failed in previous check
215
+ }
216
+ }
217
+ if (missingCount === 0 && configuredCount > 0) {
218
+ return {
219
+ status: 'passed',
220
+ message: `FRAIM server configured in all ${configuredCount} IDE(s)`,
221
+ details: { configuredCount }
222
+ };
223
+ }
224
+ if (missingCount > 0) {
225
+ return {
226
+ status: 'warning',
227
+ message: `FRAIM server missing in ${missingCount} IDE(s): ${missing.join(', ')}`,
228
+ suggestion: 'Run fraim add-ide to configure FRAIM server',
229
+ command: 'fraim add-ide',
230
+ details: { missing, configuredCount, missingCount }
231
+ };
232
+ }
233
+ return {
234
+ status: 'passed',
235
+ message: 'No IDEs with MCP configs to check'
236
+ };
237
+ }
238
+ };
239
+ }
240
+ /**
241
+ * Get all IDE configuration checks
242
+ */
243
+ function getIDEConfigChecks() {
244
+ return [
245
+ checkIDEsDetected(),
246
+ checkMCPConfigsExist(),
247
+ checkMCPConfigsValid(),
248
+ checkFraimServerConfigured()
249
+ ];
250
+ }