mcp-prompt-optimizer 1.5.0 → 2.2.3

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.
@@ -15,7 +15,7 @@ const packageJson = require('../package.json');
15
15
  class CloudApiKeyManager {
16
16
  constructor(apiKey, options = {}) {
17
17
  this.apiKey = apiKey;
18
- this.backendUrl = options.backendUrl || process.env.OPTIMIZER_BACKEND_URL || 'https://p01--project-optimizer--fvrdk8m9k9j.code.run';
18
+ this.backendUrl = options.backendUrl || process.env.OPTIMIZER_BACKEND_URL || 'https://p01--project-optimizer--fvmrdk8m9k9j.code.run';
19
19
  this.cacheFile = path.join(os.homedir(), '.mcp-cloud-api-cache.json');
20
20
  this.healthFile = path.join(os.homedir(), '.mcp-cloud-health.json');
21
21
  this.cacheExpiry = options.cacheExpiry || 24 * 60 * 60 * 1000; // 24 hours
@@ -196,8 +196,7 @@ class CloudApiKeyManager {
196
196
 
197
197
  this.log(`API key format valid: ${formatCheck.keyType}`);
198
198
 
199
- // Step 2: Development mode handling
200
- if (this.developmentMode || formatCheck.keyType === 'development' || formatCheck.keyType === 'testing') {
199
+ if (this.developmentMode || formatCheck.keyType === 'testing') {
201
200
  this.log('Development/testing mode detected, using mock validation', 'warn');
202
201
  const mockValidation = this.generateMockValidation(formatCheck.keyType);
203
202
  await this.cacheValidation(mockValidation);
@@ -290,99 +289,23 @@ class CloudApiKeyManager {
290
289
 
291
290
  // ✅ FIXED: Correct API endpoint URL
292
291
  async validateWithBackend() {
293
- return new Promise((resolve, reject) => {
294
- const url = `${this.backendUrl}/api/v1/mcp/validate-key`;
295
-
296
- const options = {
297
- method: 'GET',
298
- headers: {
299
- 'x-api-key': this.apiKey,
300
- 'Content-Type': 'application/json',
301
- 'User-Agent': `mcp-prompt-optimizer/${packageJson.version}`,
302
- 'Accept': 'application/json',
303
- 'Connection': 'close' // Ensure connection cleanup
304
- },
305
- timeout: this.requestTimeout
306
- };
307
-
308
- this.log(`Making request to: ${url}`);
309
- this.log(`Using API key: ${this.apiKey.substring(0, 16)}...`);
310
-
311
- const client = this.backendUrl.startsWith('https://') ? https : http;
312
- const req = client.request(url, options, (res) => {
313
- let data = '';
314
-
315
- res.on('data', (chunk) => {
316
- data += chunk;
317
- });
318
-
319
- res.on('end', () => {
320
- this.log(`Response status: ${res.statusCode}`);
321
-
322
- try {
323
- if (res.statusCode === 200) {
324
- const validation = JSON.parse(data);
325
- this.log(`Validation successful: ${JSON.stringify(validation, null, 2)}`);
326
- resolve(validation);
327
- } else if (res.statusCode === 401) {
328
- reject(new Error('Invalid API key or unauthorized access'));
329
- } else if (res.statusCode === 403) {
330
- reject(new Error('API key expired or quota exceeded'));
331
- } else if (res.statusCode === 429) {
332
- reject(new Error('Rate limit exceeded. Please try again later.'));
333
- } else if (res.statusCode === 500) {
334
- reject(new Error('Backend server error. Please try again later.'));
335
- } else if (res.statusCode === 503) {
336
- reject(new Error('Backend service temporarily unavailable. Please try again later.'));
337
- } else {
338
- let errorMessage;
339
- try {
340
- const error = JSON.parse(data);
341
- errorMessage = error.detail || error.message || `HTTP ${res.statusCode}`;
342
- } catch {
343
- errorMessage = `HTTP ${res.statusCode}: ${data}`;
344
- }
345
- reject(new Error(errorMessage));
346
- }
347
- } catch (parseError) {
348
- this.log(`Parse error: ${parseError.message}`, 'error');
349
- this.log(`Raw response: ${data}`, 'error');
350
- reject(new Error(`Invalid response format: ${parseError.message}`));
351
- }
352
- });
353
- });
354
-
355
- req.on('error', (error) => {
356
- this.log(`Network error: ${error.message}`, 'error');
357
-
358
- // Enhanced error classification
359
- if (error.code === 'ENOTFOUND') {
360
- reject(new Error(`DNS resolution failed: Cannot resolve ${this.backendUrl.replace(/^https?:\/\//, '')}`));
361
- } else if (error.code === 'ECONNREFUSED') {
362
- reject(new Error(`Connection refused: Backend server may be down`));
363
- } else if (error.code === 'ETIMEDOUT') {
364
- reject(new Error(`Connection timeout: Backend server is not responding`));
365
- } else if (error.code === 'ECONNRESET') {
366
- reject(new Error(`Connection reset: Network instability detected`));
367
- } else {
368
- reject(new Error(`Network error: ${error.message}`));
369
- }
370
- });
371
-
372
- req.on('timeout', () => {
373
- req.destroy();
374
- reject(new Error('Request timeout - backend may be unavailable'));
375
- });
376
-
377
- req.setTimeout(this.requestTimeout);
378
- req.end();
379
- });
292
+ const endpoint = '/api/v1/api-keys/validate';
293
+ const method = 'POST';
294
+
295
+ try {
296
+ const validation = await this._makeBackendRequest(endpoint, null, method);
297
+ this.log(`Validation successful: ${JSON.stringify(validation, null, 2)}`);
298
+ return validation;
299
+ } catch (error) {
300
+ this.log(`Backend validation request failed: ${error.message}`, 'error');
301
+ throw error;
302
+ }
380
303
  }
381
304
 
382
305
  // ✅ FIXED: Correct API endpoint URL
383
306
  async getQuotaStatus() {
384
307
  try {
385
- const url = `${this.backendUrl}/api/v1/mcp/quota-status`;
308
+ const url = `${this.backendUrl}/api/v1/api-keys/quota-status`;
386
309
 
387
310
  const options = {
388
311
  method: 'GET',
@@ -462,38 +385,7 @@ class CloudApiKeyManager {
462
385
  }
463
386
  }
464
387
 
465
- // Enhanced quota status checking
466
- async checkQuotaStatus(validation) {
467
- const quota = validation.quota || {};
468
-
469
- if (quota.unlimited) {
470
- return { allowed: true, unlimited: true };
471
- }
472
388
 
473
- const quotaUsed = quota.used || 0;
474
- const quotaLimit = quota.limit || 5000;
475
- const quotaRemaining = quota.remaining || (quotaLimit - quotaUsed);
476
-
477
- if (quotaUsed >= quotaLimit) {
478
- const tier = validation.tier || 'explorer';
479
- const upgradeMessage = tier === 'explorer'
480
- ? 'Upgrade to Creator ($25.99/mo) for 18,000 optimizations: https://promptoptimizer-blog.vercel.app/pricing'
481
- : 'Quota will reset on your next billing cycle.';
482
-
483
- throw new Error(
484
- `Monthly quota exceeded (${quotaUsed}/${quotaLimit}). ${upgradeMessage}`
485
- );
486
- }
487
-
488
- return {
489
- allowed: true,
490
- unlimited: false,
491
- used: quotaUsed,
492
- limit: quotaLimit,
493
- remaining: quotaRemaining,
494
- usage_percentage: (quotaUsed / quotaLimit) * 100
495
- };
496
- }
497
389
 
498
390
  // Enhanced caching with metadata
499
391
  async cacheValidation(validation) {
@@ -593,13 +485,10 @@ class CloudApiKeyManager {
593
485
  // Step 1: Validate API key
594
486
  const validation = await this.validateApiKey();
595
487
 
596
- // Step 2: Check quota (skip for development/mock modes)
597
- let quotaStatus;
598
- if (validation.mock_mode || validation.fallback_mode || validation.offline_mode) {
599
- quotaStatus = validation.quota || { allowed: true, unlimited: true };
600
- } else {
601
- quotaStatus = await this.checkQuotaStatus(validation);
602
- }
488
+ // Step 2: Get comprehensive quota status
489
+ const info = await this.getApiKeyInfo();
490
+ let quotaStatus = info.quota;
491
+ validation = info; // Use info as the main validation object for consistency
603
492
 
604
493
  // Step 3: Log success
605
494
  const mode = validation.mock_mode ? '(mock)' :
@@ -633,24 +522,57 @@ class CloudApiKeyManager {
633
522
 
634
523
  // Enhanced API key info with mode detection
635
524
  async getApiKeyInfo() {
525
+ const formatCheck = this.validateApiKeyFormat(this.apiKey);
526
+ if (this.developmentMode || formatCheck.keyType === 'development' || formatCheck.keyType === 'testing') {
527
+ this.log('Development/testing mode detected for getApiKeyInfo, returning mock data.', 'warn');
528
+ return {
529
+ tier: 'testing',
530
+ features: {
531
+ optimization: true,
532
+ template_search: true,
533
+ template_auto_save: true,
534
+ optimization_insights: true,
535
+ bayesian_optimization: true,
536
+ agui_features: true
537
+ },
538
+ quota: {
539
+ unlimited: false,
540
+ used: Math.floor(Math.random() * 100),
541
+ limit: 1000,
542
+ remaining: 1000 - Math.floor(Math.random() * 100)
543
+ },
544
+ isValid: true,
545
+ keyType: formatCheck.keyType,
546
+ mode: {
547
+ mock: true,
548
+ fallback: false,
549
+ offline: false,
550
+ development: this.developmentMode
551
+ }
552
+ };
553
+ }
554
+
636
555
  try {
637
- const validation = await this.validateApiKey();
638
- const quotaStatus = await this.checkQuotaStatus(validation);
556
+ // Directly call the new quota-status endpoint
557
+ const quotaStatusResponse = await this._makeBackendRequest('/api/v1/api-keys/quota-status', null, 'GET');
639
558
 
559
+ // The backend /mcp/quota-status endpoint returns a comprehensive object
560
+ // that includes tier, quota details, and features.
640
561
  return {
641
- tier: validation.tier,
642
- features: validation.features || {},
643
- quota: quotaStatus,
562
+ tier: quotaStatusResponse.tier,
563
+ features: quotaStatusResponse.features_available || {},
564
+ quota: quotaStatusResponse.quota,
644
565
  isValid: true,
645
- keyType: validation.api_key_type || this.validateApiKeyFormat(this.apiKey).keyType,
566
+ keyType: quotaStatusResponse.account_type || this.validateApiKeyFormat(this.apiKey).keyType,
646
567
  mode: {
647
- mock: validation.mock_mode || false,
648
- fallback: validation.fallback_mode || false,
649
- offline: validation.offline_mode || false,
568
+ mock: false, // This endpoint doesn't return mock status
569
+ fallback: false,
570
+ offline: false,
650
571
  development: this.developmentMode
651
572
  }
652
573
  };
653
574
  } catch (error) {
575
+ this.log(`Error getting API key info: ${error.message}`, 'error');
654
576
  return {
655
577
  tier: null,
656
578
  features: {},
@@ -692,6 +614,137 @@ class CloudApiKeyManager {
692
614
  if (!this.apiKey) return 'No key';
693
615
  return `${this.apiKey.substring(0, 8)}...${this.apiKey.slice(-4)}`;
694
616
  }
617
+
618
+ async getDiagnosticInfo() {
619
+ const diagnosticInfo = {
620
+ apiKey: this.apiKey ? this.formatKeyForDisplay() : 'Not set',
621
+ backendUrl: this.backendUrl,
622
+ cacheFile: this.cacheFile,
623
+ healthFile: this.healthFile,
624
+ cacheExpiry: this.cacheExpiry,
625
+ fallbackCacheExpiry: this.fallbackCacheExpiry,
626
+ offlineMode: this.offlineMode,
627
+ developmentMode: this.developmentMode,
628
+ maxRetries: this.maxRetries,
629
+ requestTimeout: this.requestTimeout,
630
+ nodeEnv: process.env.NODE_ENV || 'not set',
631
+ packageVersion: packageJson.version,
632
+ networkHealth: { ...this.networkHealth },
633
+ cache: {},
634
+ keyFormat: this.validateApiKeyFormat(this.apiKey),
635
+ backendConnectivity: { status: 'unknown', error: null, responseTime: null }
636
+ };
637
+
638
+ // Get cache status
639
+ try {
640
+ const cached = await this.getCachedValidation();
641
+ if (cached) {
642
+ diagnosticInfo.cache.exists = true;
643
+ diagnosticInfo.cache.expired = this.isCacheExpired(cached);
644
+ diagnosticInfo.cache.fallbackExpired = this.isFallbackCacheExpired(cached);
645
+ diagnosticInfo.cache.age = Math.round((Date.now() - cached.timestamp) / 1000 / 60);
646
+ diagnosticInfo.cache.backendUrl = cached.backendUrl;
647
+ diagnosticInfo.cache.packageVersion = cached.packageVersion;
648
+ } else {
649
+ diagnosticInfo.cache.exists = false;
650
+ }
651
+ } catch (error) {
652
+ diagnosticInfo.cache.error = error.message;
653
+ diagnosticInfo.cache.exists = false;
654
+ }
655
+
656
+ // Check backend connectivity
657
+ if (this.apiKey) { // Only check if API key is present
658
+ try {
659
+ const startTime = Date.now();
660
+ await this.validateWithBackend(); // This will attempt to connect to the backend
661
+ const responseTime = Date.now() - startTime;
662
+ diagnosticInfo.backendConnectivity.status = 'success';
663
+ diagnosticInfo.backendConnectivity.responseTime = responseTime;
664
+ } catch (error) {
665
+ diagnosticInfo.backendConnectivity.status = 'failed';
666
+ diagnosticInfo.backendConnectivity.error = error.message;
667
+ }
668
+ } else {
669
+ diagnosticInfo.backendConnectivity.status = 'skipped';
670
+ diagnosticInfo.backendConnectivity.error = 'No API key provided for connectivity check.';
671
+ }
672
+
673
+ return diagnosticInfo;
674
+ }
675
+
676
+ async _makeBackendRequest(endpoint, data, method = 'POST') {
677
+ return new Promise((resolve, reject) => {
678
+ const url = `${this.backendUrl}${endpoint}`;
679
+
680
+ const options = {
681
+ method: method,
682
+ headers: {
683
+ 'x-api-key': this.apiKey,
684
+ 'Content-Type': 'application/json',
685
+ 'User-Agent': `mcp-prompt-optimizer/${packageJson.version}`,
686
+ 'Accept': 'application/json',
687
+ 'Connection': 'close'
688
+ },
689
+ timeout: this.requestTimeout
690
+ };
691
+
692
+ const client = this.backendUrl.startsWith('https://') ? https : http;
693
+ const req = client.request(url, options, (res) => {
694
+ let responseData = '';
695
+
696
+ res.on('data', (chunk) => {
697
+ responseData += chunk;
698
+ });
699
+
700
+ res.on('end', () => {
701
+ try {
702
+ if (res.statusCode >= 200 && res.statusCode < 300) {
703
+ const parsed = JSON.parse(responseData);
704
+ resolve(parsed);
705
+ } else {
706
+ let errorMessage;
707
+ try {
708
+ const error = JSON.parse(responseData);
709
+ errorMessage = error.detail || error.message || `HTTP ${res.statusCode}`;
710
+ } catch {
711
+ errorMessage = `HTTP ${res.statusCode}: ${responseData}`;
712
+ }
713
+ reject(new Error(errorMessage));
714
+ }
715
+ } catch (parseError) {
716
+ reject(new Error(`Invalid response format: ${parseError.message}`));
717
+ }
718
+ });
719
+ });
720
+
721
+ req.on('error', (error) => {
722
+ if (error.code === 'ENOTFOUND') {
723
+ reject(new Error(`DNS resolution failed: Cannot resolve ${this.backendUrl.replace(/^https?:\/\//, '')}`));
724
+ } else if (error.code === 'ECONNREFUSED') {
725
+ reject(new Error(`Connection refused: Backend server may be down`));
726
+ } else if (error.code === 'ETIMEDOUT') {
727
+ reject(new Error(`Connection timeout: Backend server is not responding`));
728
+ } else if (error.code === 'ECONNRESET') {
729
+ reject(new Error(`Connection reset: Network instability detected`));
730
+ } else {
731
+ reject(new Error(`Network error: ${error.message}`));
732
+ }
733
+ });
734
+
735
+ req.on('timeout', () => {
736
+ req.destroy();
737
+ reject(new Error('Request timeout - backend may be unavailable'));
738
+ });
739
+
740
+ req.setTimeout(this.requestTimeout);
741
+
742
+ if (method !== 'GET' && data) {
743
+ req.write(JSON.stringify(data));
744
+ }
745
+ req.end();
746
+ });
747
+ }
695
748
  }
696
749
 
697
750
  module.exports = CloudApiKeyManager;
@@ -10,7 +10,7 @@ async function checkStatus() {
10
10
  if (!apiKey) {
11
11
  console.error('❌ No API key found');
12
12
  console.log('\n📝 Set your API key to check status:');
13
- console.log(' export OPTIMIZER_API_KEY=sk-opt-your-key-here');
13
+ console.log(' export OPTIMIZER_API_KEY=sk-local-your-key-here'); // Aligned with free tier/development
14
14
  if (developmentMode) {
15
15
  console.log('\n🧪 Development Mode Options:');
16
16
  console.log(' export OPTIMIZER_API_KEY=sk-dev-test-key');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-prompt-optimizer",
3
- "version": "1.5.0",
3
+ "version": "2.2.3",
4
4
  "description": "Professional cloud-based MCP server for AI-powered prompt optimization with intelligent context detection, Bayesian optimization, AG-UI real-time optimization, template auto-save, optimization insights, personal model configuration via WebUI, team collaboration, enterprise-grade features, production resilience, and startup validation. Universal compatibility with Claude Desktop, Cursor, Windsurf, and 17+ MCP clients.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -23,6 +23,7 @@
23
23
  "test:integration": "node tests/integration-test.js",
24
24
  "test:comprehensive": "node tests/comprehensive-test.js",
25
25
  "test:runner": "node tests/test-runner.js",
26
+ "test:simple": "node tests/simple-test.js",
26
27
  "pretest": "npm run health-check",
27
28
  "prepublishOnly": "npm run test:quick",
28
29
  "version": "echo 'Updating version...' && npm run test:quick"
@@ -111,7 +112,6 @@
111
112
  "files": [
112
113
  "index.js",
113
114
  "lib/",
114
- "tests/",
115
115
  "README.md",
116
116
  "CHANGELOG.md",
117
117
  "CROSS-PLATFORM.md",
@@ -218,7 +218,7 @@
218
218
  }
219
219
  },
220
220
  "backend_alignment": {
221
- "version": "production-v2.1.0-bayesian",
221
+ "version": "production-v2.2.0-stable",
222
222
  "api_version": "v1",
223
223
  "endpoints_aligned": true,
224
224
  "feature_parity": true,
package/tests/README.md DELETED
@@ -1,232 +0,0 @@
1
- # 🧪 MCP Prompt Optimizer Test Suite
2
-
3
- Comprehensive testing framework for validating package functionality before NPM publication.
4
-
5
- ## 📋 Test Overview
6
-
7
- ### 🚀 Quick Test (`npm run test:quick`)
8
- **Duration:** ~30 seconds
9
- **Purpose:** Rapid validation of core functionality
10
- **API Key:** Not required (uses mock mode)
11
-
12
- Tests:
13
- - ✅ Package structure validation
14
- - ✅ Cross-platform compatibility
15
- - ✅ MCP server instantiation
16
- - ✅ API key format validation
17
- - ✅ AI context detection
18
- - ✅ Mock optimization generation
19
- - ✅ Response formatting
20
- - ✅ Environment variable support
21
-
22
- **Use Case:** Quick verification during development
23
-
24
- ### 🔌 Integration Test (`npm run test:integration`)
25
- **Duration:** ~60 seconds
26
- **Purpose:** Validate API connectivity and real backend integration
27
- **API Key:** Optional (falls back to mock mode)
28
-
29
- Tests:
30
- - ✅ Backend connectivity
31
- - ✅ Real API key validation
32
- - ✅ Live optimization requests
33
- - ✅ Quota status retrieval
34
- - ✅ Template search functionality
35
- - ✅ Error recovery mechanisms
36
- - ✅ Network resilience
37
-
38
- **Use Case:** Pre-deployment validation with real backend
39
-
40
- ### 🔬 Comprehensive Test (`npm run test:comprehensive`)
41
- **Duration:** ~2 minutes
42
- **Purpose:** Exhaustive validation of all features and edge cases
43
- **API Key:** Optional (extensive mock testing)
44
-
45
- Tests:
46
- - ✅ All quick test features
47
- - ✅ All integration test features
48
- - ✅ Command-line interface testing
49
- - ✅ Network resilience scenarios
50
- - ✅ Error handling edge cases
51
- - ✅ Package integrity validation
52
- - ✅ MCP protocol compliance
53
- - ✅ Cross-platform script testing
54
-
55
- **Use Case:** Full validation before major releases
56
-
57
- ### 🎯 Test Runner (`npm test` or `npm run test:runner`)
58
- **Duration:** ~3-4 minutes
59
- **Purpose:** Orchestrates all test suites in optimal order
60
- **API Key:** Optional (runs all modes)
61
-
62
- **Use Case:** Complete pre-publication validation
63
-
64
- ## 🛠️ Usage Examples
65
-
66
- ### Basic Testing (No API Key Required)
67
- ```bash
68
- # Quick validation
69
- npm run test:quick
70
-
71
- # Full test suite in mock mode
72
- npm test
73
- ```
74
-
75
- ### Testing with Real API Key
76
- ```bash
77
- # Set your API key
78
- export OPTIMIZER_API_KEY=sk-opt-your-actual-key
79
-
80
- # Run integration tests
81
- npm run test:integration
82
-
83
- # Run full test suite
84
- npm test
85
- ```
86
-
87
- ### Development Mode Testing
88
- ```bash
89
- # Enable development mode
90
- export OPTIMIZER_DEV_MODE=true
91
- export OPTIMIZER_API_KEY=sk-dev-test-key
92
-
93
- # Run tests
94
- npm test
95
- ```
96
-
97
- ### Custom Backend Testing
98
- ```bash
99
- # Test against custom backend
100
- export OPTIMIZER_BACKEND_URL=https://your-backend.com
101
- export OPTIMIZER_API_KEY=your-key
102
-
103
- # Run integration tests
104
- npm run test:integration
105
- ```
106
-
107
- ## 📊 Test Output Examples
108
-
109
- ### ✅ Success Output
110
- ```
111
- 🎉 ALL TESTS PASSED - READY FOR PUBLICATION!
112
-
113
- 🚀 Recommended publication commands:
114
- npm publish
115
- git tag v1.4.0
116
- git push --tags
117
- ```
118
-
119
- ### ❌ Failure Output
120
- ```
121
- ❌ SOME TESTS FAILED - FIX ISSUES BEFORE PUBLICATION
122
- Run the comprehensive test suite for detailed analysis:
123
- node tests/comprehensive-test.js
124
- ```
125
-
126
- ## 🔧 Test Modes
127
-
128
- ### Mock Mode (Default)
129
- - **Trigger:** No API key provided
130
- - **Behavior:** Uses simulated responses
131
- - **Tests:** All functionality except live API calls
132
- - **Advantage:** Fast, no dependencies
133
-
134
- ### Development Mode
135
- - **Trigger:** `OPTIMIZER_DEV_MODE=true`
136
- - **Behavior:** Enhanced logging, extended timeouts
137
- - **Tests:** All functionality with debug output
138
- - **Advantage:** Detailed debugging information
139
-
140
- ### Production Mode
141
- - **Trigger:** Real API key provided
142
- - **Behavior:** Tests against live backend
143
- - **Tests:** Full end-to-end validation
144
- - **Advantage:** Real-world validation
145
-
146
- ## 🎯 Pre-Publication Checklist
147
-
148
- Run this checklist before publishing to NPM:
149
-
150
- 1. **Quick Test** ✅
151
- ```bash
152
- npm run test:quick
153
- ```
154
-
155
- 2. **Integration Test** (if you have API key) ✅
156
- ```bash
157
- OPTIMIZER_API_KEY=your-key npm run test:integration
158
- ```
159
-
160
- 3. **Full Test Suite** ✅
161
- ```bash
162
- npm test
163
- ```
164
-
165
- 4. **Manual Verification** ✅
166
- - [ ] Version number updated in package.json
167
- - [ ] CHANGELOG.md updated
168
- - [ ] README.md current
169
- - [ ] All files included in `files` array
170
-
171
- 5. **Publication** 🚀
172
- ```bash
173
- npm publish
174
- git tag v$(node -p "require('./package.json').version")
175
- git push --tags
176
- ```
177
-
178
- ## 🚨 Troubleshooting
179
-
180
- ### Common Issues
181
-
182
- **"Tests failed with exit code 1"**
183
- - Run individual test suites to identify specific failures
184
- - Check error messages for detailed debugging information
185
-
186
- **"Network error during integration tests"**
187
- - Verify internet connection
188
- - Check if backend URL is accessible
189
- - Try running in mock mode first
190
-
191
- **"API key validation failed"**
192
- - Verify API key format: `sk-opt-`, `sk-team-`, `sk-dev-`, or `sk-local-`
193
- - Check API key permissions and quota
194
- - Try development mode: `OPTIMIZER_DEV_MODE=true`
195
-
196
- **"Cross-platform script issues"**
197
- - Ensure `cross-env` is installed: `npm install`
198
- - Use platform-specific commands if needed:
199
- - Windows: `npm run dev:windows`
200
- - Unix/Mac: `npm run dev:unix`
201
-
202
- ### Debug Commands
203
-
204
- ```bash
205
- # Verbose test output
206
- DEBUG=* npm test
207
-
208
- # Individual test suites
209
- npm run test:quick
210
- npm run test:integration
211
- npm run test:comprehensive
212
-
213
- # Test specific functionality
214
- node lib/validate-key.js
215
- node lib/diagnose.js
216
- ```
217
-
218
- ## 📈 Continuous Integration
219
-
220
- For CI/CD pipelines, use:
221
-
222
- ```yaml
223
- # GitHub Actions example
224
- - name: Run tests
225
- run: |
226
- npm ci
227
- npm run test:quick
228
- env:
229
- OPTIMIZER_DEV_MODE: true
230
- ```
231
-
232
- The test suite is designed to work in CI environments without requiring real API keys.