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,264 @@
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.UsageCollector = void 0;
7
+ const mongodb_1 = require("mongodb");
8
+ const axios_1 = __importDefault(require("axios"));
9
+ // A placeholder ObjectId used when the real API key ID is not yet known.
10
+ // The server will override this with the correct ID from the authenticated API key.
11
+ const PLACEHOLDER_API_KEY_ID = new mongodb_1.ObjectId('000000000000000000000000');
12
+ /**
13
+ * Usage event collector for local MCP proxy
14
+ * Collects usage events and batches them for upload
15
+ */
16
+ class UsageCollector {
17
+ constructor() {
18
+ this.events = [];
19
+ this.apiKeyId = null;
20
+ }
21
+ static resolveMentoringJobName(args) {
22
+ if (!args || typeof args !== 'object') {
23
+ return 'unknown';
24
+ }
25
+ if (typeof args.jobName === 'string' && args.jobName.trim().length > 0) {
26
+ return args.jobName.trim();
27
+ }
28
+ // Backward compatibility for older callers and docs that still use workflowType.
29
+ if (typeof args.workflowType === 'string' && args.workflowType.trim().length > 0) {
30
+ return args.workflowType.trim();
31
+ }
32
+ if (typeof args.job === 'string' && args.job.trim().length > 0) {
33
+ return args.job.trim();
34
+ }
35
+ return 'unknown';
36
+ }
37
+ /**
38
+ * Set the API key ID for this session
39
+ */
40
+ setApiKeyId(apiKeyId) {
41
+ this.apiKeyId = apiKeyId;
42
+ }
43
+ /**
44
+ * Collect MCP tool call event
45
+ */
46
+ collectMCPCall(toolName, args, sessionId, success = true) {
47
+ const parsed = this.parseMCPCall(toolName, args);
48
+ if (!parsed) {
49
+ const errorMsg = `[UsageCollector] 🚫 Tool not tracked: ${toolName}`;
50
+ console.error(errorMsg);
51
+ // Also log to stderr for better visibility in main logs
52
+ process.stderr.write(errorMsg + '\n');
53
+ return;
54
+ }
55
+ // Extract useful args for analytics
56
+ const analyticsArgs = this.extractAnalyticsArgs(toolName, args);
57
+ const event = {
58
+ type: parsed.type,
59
+ name: parsed.name,
60
+ // Use set apiKeyId if available, otherwise a placeholder.
61
+ // The server will override this with the correct value from the auth token.
62
+ apiKeyId: this.apiKeyId || PLACEHOLDER_API_KEY_ID,
63
+ sessionId,
64
+ success,
65
+ args: analyticsArgs
66
+ };
67
+ this.events.push(event);
68
+ const successMsg = `[UsageCollector] ✅ Collected event: ${parsed.type}/${parsed.name} (session: ${sessionId}, queue: ${this.events.length})`;
69
+ console.error(successMsg);
70
+ // Also log to stderr for better visibility in main logs
71
+ process.stderr.write(successMsg + '\n');
72
+ }
73
+ /**
74
+ * Collect usage event directly (for backward compatibility with tests)
75
+ */
76
+ collectEvent(type, name, sessionId, success = true, args) {
77
+ const event = {
78
+ type,
79
+ name,
80
+ // Use set apiKeyId if available, otherwise a placeholder.
81
+ // The server will override this with the correct value from the auth token.
82
+ apiKeyId: this.apiKeyId || PLACEHOLDER_API_KEY_ID,
83
+ sessionId,
84
+ success,
85
+ args
86
+ };
87
+ this.events.push(event);
88
+ }
89
+ /**
90
+ * Extract useful arguments for analytics tracking
91
+ */
92
+ extractAnalyticsArgs(toolName, args) {
93
+ const analyticsArgs = {};
94
+ switch (toolName) {
95
+ case 'seekMentoring':
96
+ if (args.currentPhase)
97
+ analyticsArgs.currentPhase = args.currentPhase;
98
+ if (args.status)
99
+ analyticsArgs.status = args.status;
100
+ const mentoringJobName = UsageCollector.resolveMentoringJobName(args);
101
+ if (mentoringJobName !== 'unknown')
102
+ analyticsArgs.jobName = mentoringJobName;
103
+ if (args.issueNumber)
104
+ analyticsArgs.issueNumber = args.issueNumber;
105
+ break;
106
+ case 'get_fraim_file':
107
+ if (args.path) {
108
+ analyticsArgs.path = args.path;
109
+ // Extract category and subcategory from path
110
+ const pathParts = args.path.split('/');
111
+ if (pathParts.length >= 2) {
112
+ analyticsArgs.category = pathParts[1]; // skills, jobs, rules, workflows
113
+ if (pathParts.length >= 3) {
114
+ analyticsArgs.subcategory = pathParts[2]; // engineering, product-building, etc.
115
+ }
116
+ }
117
+ }
118
+ break;
119
+ case 'get_fraim_job':
120
+ if (args.job)
121
+ analyticsArgs.job = args.job;
122
+ break;
123
+ case 'fraim_connect':
124
+ if (args.agent?.name)
125
+ analyticsArgs.agentName = args.agent.name;
126
+ if (args.agent?.model)
127
+ analyticsArgs.agentModel = args.agent.model;
128
+ break;
129
+ default:
130
+ // For other tools, don't collect args to avoid PII
131
+ return undefined;
132
+ }
133
+ return Object.keys(analyticsArgs).length > 0 ? analyticsArgs : undefined;
134
+ }
135
+ /**
136
+ * Parse MCP tool call to extract usage analytics info
137
+ */
138
+ parseMCPCall(toolName, args) {
139
+ switch (toolName) {
140
+ case 'get_fraim_job':
141
+ return { type: 'job', name: args.job || 'unknown' };
142
+ case 'get_fraim_file':
143
+ if (args.path) {
144
+ return UsageCollector.parseComponentName(args.path);
145
+ }
146
+ return null;
147
+ case 'seekMentoring':
148
+ return { type: 'mentoring', name: UsageCollector.resolveMentoringJobName(args) };
149
+ case 'list_fraim_jobs':
150
+ return { type: 'job', name: 'list' };
151
+ case 'fraim_connect':
152
+ return { type: 'session', name: 'connect' };
153
+ default:
154
+ return null;
155
+ }
156
+ }
157
+ /**
158
+ * Get collected events for upload and clear the queue
159
+ */
160
+ getEventsForUpload() {
161
+ const eventsToUpload = [...this.events];
162
+ this.events = [];
163
+ return eventsToUpload;
164
+ }
165
+ /**
166
+ * Get current event count
167
+ */
168
+ getEventCount() {
169
+ return this.events.length;
170
+ }
171
+ /**
172
+ * Flush events to the remote server via API
173
+ */
174
+ async flush(remoteUrl, apiKey) {
175
+ if (this.events.length === 0) {
176
+ const noEventsMsg = `[UsageCollector] 📊 No events to flush`;
177
+ console.error(noEventsMsg);
178
+ process.stderr.write(noEventsMsg + '\n');
179
+ return;
180
+ }
181
+ const events = [...this.events];
182
+ this.events = [];
183
+ const flushMsg = `[UsageCollector] 📤 Flushing ${events.length} events to ${remoteUrl}/api/analytics/events`;
184
+ console.error(flushMsg);
185
+ process.stderr.write(flushMsg + '\n');
186
+ try {
187
+ const response = await axios_1.default.post(`${remoteUrl}/api/analytics/events`, {
188
+ events,
189
+ apiKey
190
+ }, {
191
+ timeout: 5000,
192
+ headers: {
193
+ 'x-api-key': apiKey,
194
+ 'Content-Type': 'application/json'
195
+ }
196
+ });
197
+ const successMsg = `[UsageCollector] ✅ Successfully flushed ${events.length} events (HTTP ${response.status})`;
198
+ console.error(successMsg);
199
+ process.stderr.write(successMsg + '\n');
200
+ // Success - events are already cleared from the queue
201
+ }
202
+ catch (error) {
203
+ const status = error.response?.status;
204
+ const message = error.response?.data?.error || error.message;
205
+ const errorMsg = `[UsageCollector] ❌ Failed to flush usage events (HTTP ${status}): ${message}`;
206
+ console.error(errorMsg);
207
+ process.stderr.write(errorMsg + '\n');
208
+ // Log additional debug info
209
+ if (error.response?.data) {
210
+ const debugMsg = `[UsageCollector] 🔍 Response data: ${JSON.stringify(error.response.data)}`;
211
+ console.error(debugMsg);
212
+ process.stderr.write(debugMsg + '\n');
213
+ }
214
+ // Put events back at the beginning of the queue for next try
215
+ this.events = [...events, ...this.events];
216
+ // Re-throw the error so the main server can log it too
217
+ throw error;
218
+ }
219
+ }
220
+ /**
221
+ * Shutdown the collector
222
+ */
223
+ shutdown() {
224
+ this.events = [];
225
+ }
226
+ /**
227
+ * Parse component name from file path
228
+ */
229
+ static parseComponentName(path) {
230
+ // Normalize path to have leading slash for consistent regex matching
231
+ const normalizedPath = path.startsWith('/') ? path : `/${path}`;
232
+ // Match skills files: /skills/category/skill-name.md
233
+ if (normalizedPath.includes('/skills/')) {
234
+ const skillMatch = normalizedPath.match(/\/skills\/[^/]+\/([^/]+)\.md$/);
235
+ if (skillMatch) {
236
+ return { type: 'skill', name: skillMatch[1] };
237
+ }
238
+ }
239
+ // Match job files: /jobs/category/subcategory/job-name.md
240
+ if (normalizedPath.includes('/jobs/')) {
241
+ const jobMatch = normalizedPath.match(/\/jobs\/[^/]+\/[^/]+\/([^/]+)\.md$/);
242
+ if (jobMatch) {
243
+ return { type: 'job', name: jobMatch[1] };
244
+ }
245
+ }
246
+ // Match rule files: /rules/category/rule-name.md
247
+ if (normalizedPath.includes('/rules/')) {
248
+ const ruleMatch = normalizedPath.match(/\/rules\/[^/]+\/([^/]+)\.md$/);
249
+ if (ruleMatch) {
250
+ return { type: 'rule', name: ruleMatch[1] };
251
+ }
252
+ }
253
+ // For other paths that don't match the expected patterns,
254
+ // we'll classify them as 'job' type with a generic name
255
+ // This ensures we track usage even for non-standard paths
256
+ const fileName = normalizedPath.split('/').pop();
257
+ if (fileName && fileName.endsWith('.md')) {
258
+ const baseName = fileName.replace(/\.md$/, '');
259
+ return { type: 'job', name: baseName };
260
+ }
261
+ return null;
262
+ }
263
+ }
264
+ exports.UsageCollector = UsageCollector;
package/index.js ADDED
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * FRAIM Framework - Smart Entry Point
5
+ * This file handles both production (dist/) and development (src/) environments.
6
+ */
7
+
8
+ const path = require('path');
9
+ const fs = require('fs');
10
+ const { spawnSync } = require('child_process');
11
+
12
+ /**
13
+ * Runs the CLI using either the compiled JS or the source TS via tsx
14
+ */
15
+ function runCLI() {
16
+ const distPath = path.join(__dirname, 'dist', 'src', 'cli', 'fraim.js');
17
+ const srcPath = path.join(__dirname, 'src', 'cli', 'fraim.ts');
18
+
19
+ // 1. Check if we have a compiled version (Production / CI)
20
+ if (fs.existsSync(distPath)) {
21
+ require(distPath);
22
+ return;
23
+ }
24
+
25
+ // 2. Explicitly fail in production if dist/ is missing
26
+ if (process.env.NODE_ENV === 'production') {
27
+ console.error('❌ FRAIM Error: Production build (dist/) not found.');
28
+ console.error('In production environments, you must run the compiled version.');
29
+ console.error(`Expected: ${distPath}`);
30
+ process.exit(1);
31
+ }
32
+
33
+ // 3. Fallback to source version using tsx (Development)
34
+ if (fs.existsSync(srcPath)) {
35
+ // We use spawnSync to run tsx so we don't have to require it in memory
36
+ // if it's not needed, and it handles the process arguments correctly.
37
+ //
38
+ // IMPORTANT FIX: Directory names with spaces and dashes (e.g., "FRAIM - Issue 166")
39
+ // cause argument parsing issues on Windows when shell: true is used.
40
+ // Without quoting, a path like "C:\...\FRAIM - Issue 166\src\cli\fraim.ts" gets
41
+ // split into multiple arguments, with the dash interpreted as a command flag,
42
+ // resulting in "error: unknown command '-'".
43
+ //
44
+ // Solution: On Windows with shell: true, quote paths containing spaces.
45
+ // On Unix with shell: false, pass the path unquoted (spawnSync handles it correctly).
46
+ const isWindows = process.platform === 'win32';
47
+
48
+ // On Windows with shell, quote paths with spaces to prevent shell misinterpretation
49
+ // On Unix without shell, pass path as-is (spawnSync handles spaces correctly)
50
+ const processedSrcPath = (isWindows && srcPath.includes(' '))
51
+ ? `"${srcPath}"`
52
+ : srcPath;
53
+
54
+ const result = spawnSync(
55
+ 'npx',
56
+ ['tsx', processedSrcPath, ...process.argv.slice(2)],
57
+ {
58
+ stdio: 'inherit',
59
+ shell: isWindows, // Windows needs shell for npx, Unix doesn't
60
+ windowsHide: true
61
+ }
62
+ );
63
+ process.exit(result.status || 0);
64
+ }
65
+
66
+ console.error('❌ FRAIM Error: Could not find CLI entry point.');
67
+ console.error('Expected one of:');
68
+ console.error(` - ${distPath}`);
69
+ console.error(` - ${srcPath}`);
70
+ process.exit(1);
71
+ }
72
+
73
+ // Global programmatic exports
74
+ module.exports = {
75
+ FRAIM_INFO: {
76
+ name: 'FRAIM',
77
+ version: '2.0.98',
78
+ repository: 'https://github.com/mathursrus/FRAIM'
79
+ }
80
+ };
81
+
82
+ // If this file is run directly (via npx or global link), run the CLI
83
+ if (require.main === module) {
84
+ runCLI();
85
+ }
package/package.json ADDED
@@ -0,0 +1,139 @@
1
+ {
2
+ "name": "fraim",
3
+ "version": "2.0.100",
4
+ "description": "FRAIM CLI - Framework for Rigor-based AI Management (alias for fraim-framework)",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "fraim": "./index.js",
8
+ "fraim-framework": "./index.js"
9
+ },
10
+ "scripts": {
11
+ "dev": "tsx --watch src/fraim-mcp-server.ts > server.log 2>&1",
12
+ "dev:prod": "npm run build && node dist/src/fraim-mcp-server.js > server.log 2>&1",
13
+ "build": "tsc && npm run build:stubs && npm run build:fraim-brain && node scripts/copy-registry.js && node -e \"require('fs').copyFileSync('src/core/types.ts', 'registry/templates/manager/fraim-config-schema.ts')\" && npm run validate:registry && npm run validate:fraim-pro-assets && tsx scripts/validate-purity.ts",
14
+ "build:stubs": "tsx scripts/build-stub-registry.ts",
15
+ "build:fraim-brain": "node scripts/generate-fraim-brain.js",
16
+ "test-all": "npm run test && npm run test:isolated && npm run test:ui",
17
+ "test": "node scripts/test-with-server.js",
18
+ "test:isolated": "npx tsx --test --test-reporter=spec tests/isolated/test-*.ts",
19
+ "test:smoke": "node scripts/test-with-server.js tests/test-*.ts --tags=smoke",
20
+ "test:stripe": "node scripts/test-with-server.js tests/test-stripe-payment-complete.ts",
21
+ "test:stripe:ui": "playwright test tests/ui/test-payment-ui.spec.ts",
22
+ "test:ui": "playwright test",
23
+ "test:ui:headed": "playwright test --headed",
24
+ "start:fraim": "tsx src/fraim-mcp-server.ts",
25
+ "dev:fraim": "tsx --watch src/fraim-mcp-server.ts",
26
+ "serve:website": "node fraim-pro/serve.js",
27
+ "watch:fraimlogs": "tsx scripts/watch-fraim-logs.ts > prodlogs.log 2>&1",
28
+ "manage-keys": "tsx scripts/fraim/manage-keys.ts",
29
+ "partner-discounts": "tsx scripts/fraim/manage-partner-discounts.ts",
30
+ "fix-key": "tsx scripts/fraim/fix-expired-key.ts",
31
+ "setup-stripe-webhook": "tsx scripts/fraim/setup-stripe-webhook.ts",
32
+ "view-signups": "tsx scripts/view-signups.ts",
33
+ "fraim:init": "npm run build && node index.js init",
34
+ "fraim:sync": "node index.js sync --local",
35
+ "postinstall": "fraim sync --skip-updates || echo 'FRAIM setup skipped.'",
36
+ "prepublishOnly": "npm run build",
37
+ "release": "npm version patch && npm run publish-both",
38
+ "publish-both": "node scripts/publish-both.js",
39
+ "publish-fraim-only": "node scripts/publish-fraim.js",
40
+ "publish-both-manual": "node scripts/publish-both.js",
41
+ "validate:registry": "tsx scripts/verify-registry-paths.ts && npm run validate:jobs && npm run validate:skills && npm run validate:registry-references && npm run validate:platform-agnostic && npm run validate:template-namespaces && npm run validate:config-fallbacks && npm run validate:bootstrap-config-coverage && npm run validate:provider-action-mappings && npm run validate:fidelity && npm run validate:config-tokens && npm run validate:brain-mapping && npm run validate:template-syntax",
42
+ "validate:registry-references": "tsx scripts/validate-registry-references.ts",
43
+ "validate:brain-mapping": "tsx scripts/validate-brain-mapping.ts",
44
+ "validate:fraim-pro-assets": "tsx scripts/validate-fraim-pro-assets.ts",
45
+ "validate:jobs": "tsx scripts/validate-jobs.ts",
46
+ "validate:platform-agnostic": "tsx scripts/validate-platform-agnostic.ts",
47
+ "validate:skills": "tsx scripts/validate-skills.ts",
48
+ "validate:template-namespaces": "tsx scripts/validate-template-namespaces.ts",
49
+ "validate:config-fallbacks": "tsx scripts/validate-config-fallbacks.ts",
50
+ "validate:bootstrap-config-coverage": "tsx scripts/validate-bootstrap-config-coverage.ts",
51
+ "validate:provider-action-mappings": "tsx scripts/validate-provider-action-mappings.ts",
52
+ "validate:fidelity": "tsx scripts/validate-fidelity.ts",
53
+ "validate:config-tokens": "tsx scripts/validate-config-tokens.ts",
54
+ "validate:template-syntax": "tsx scripts/validate-template-syntax.ts"
55
+ },
56
+ "repository": {
57
+ "type": "git",
58
+ "url": "git+https://github.com/mathursrus/FRAIM.git"
59
+ },
60
+ "keywords": [
61
+ "fraim",
62
+ "ai-management",
63
+ "ai-coordination",
64
+ "ai-agents",
65
+ "multi-agent",
66
+ "github",
67
+ "automation",
68
+ "gitops",
69
+ "cursor",
70
+ "claude",
71
+ "windsurf",
72
+ "rigor",
73
+ "enterprise",
74
+ "framework",
75
+ "ai-managers"
76
+ ],
77
+ "author": "Sid Mathur <sid.mathur@gmail.com>",
78
+ "license": "MIT",
79
+ "bugs": {
80
+ "url": "https://github.com/mathursrus/FRAIM/issues"
81
+ },
82
+ "homepage": "https://github.com/mathursrus/FRAIM#readme",
83
+ "engines": {
84
+ "node": ">=16.0.0"
85
+ },
86
+ "devDependencies": {
87
+ "@playwright/test": "^1.58.2",
88
+ "@types/adm-zip": "^0.5.7",
89
+ "@types/cors": "^2.8.19",
90
+ "@types/express": "^5.0.6",
91
+ "@types/node": "^20.0.0",
92
+ "@types/prompts": "^2.4.9",
93
+ "@types/semver": "^7.7.1",
94
+ "fast-glob": "^3.3.3",
95
+ "html-to-docx": "^1.8.0",
96
+ "markdown-it": "^14.1.1",
97
+ "markdown-it-highlightjs": "^4.3.0",
98
+ "playwright": "^1.58.2",
99
+ "pptxgenjs": "^4.0.1",
100
+ "puppeteer": "^24.36.1",
101
+ "qrcode": "^1.5.4",
102
+ "sharp": "^0.34.5",
103
+ "tsx": "^4.0.0",
104
+ "typescript": "^5.0.0"
105
+ },
106
+ "files": [
107
+ "dist/src/local-mcp-server/",
108
+ "dist/src/cli/",
109
+ "dist/src/core/",
110
+ "bin/fraim.js",
111
+ "bin/fraim-mcp.js",
112
+ "index.js",
113
+ "README.md",
114
+ "CHANGELOG.md",
115
+ "LICENSE",
116
+ "package.json"
117
+ ],
118
+ "publishConfig": {
119
+ "access": "public"
120
+ },
121
+ "dependencies": {
122
+ "adm-zip": "^0.5.16",
123
+ "axios": "^1.7.0",
124
+ "chalk": "4.1.2",
125
+ "commander": "^14.0.2",
126
+ "cors": "^2.8.5",
127
+ "dotenv": "^16.4.7",
128
+ "express": "^5.2.1",
129
+ "mongodb": "^7.0.0",
130
+ "node-edge-tts": "^1.2.10",
131
+ "prompts": "^2.4.2",
132
+ "resend": "^6.9.3",
133
+ "semver": "^7.7.4",
134
+ "stripe": "^20.3.1",
135
+ "toml": "^3.0.0",
136
+ "tree-kill": "^1.2.2",
137
+ "xml2js": "^0.6.2"
138
+ }
139
+ }