Skip to content

Commit 945e2cd

Browse files
committed
fixed extra logs
1 parent 99a04e5 commit 945e2cd

7 files changed

Lines changed: 51 additions & 109 deletions

File tree

src/commands/fix.ts

Lines changed: 15 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@ import { handleError, Errors } from '../utils/errorHandler';
1212

1313
export async function fixCommand(options: { yes?: boolean } = {}) {
1414
try {
15-
console.log(chalk.bold.cyan('\n🔧 TunePrompt Fix\n'));
15+
console.log('');
1616

17-
// License check with better error
1817
const spinner = ora('Checking license...').start();
1918
const licenseValid = await checkLicense();
2019

@@ -26,39 +25,32 @@ export async function fixCommand(options: { yes?: boolean } = {}) {
2625

2726
spinner.succeed('License validated');
2827

29-
// Load failed tests with error handling
3028
const failedTests = await getFailedTests();
3129

3230
if (failedTests.length === 0) {
3331
throw Errors.NO_FAILED_TESTS;
3432
}
3533

36-
console.log(chalk.yellow(`\nFound ${failedTests.length} failed test(s):\n`));
34+
console.log(chalk.yellow(`\n${failedTests.length} failed test(s):`));
3735

3836
failedTests.forEach((test: FailedTest, index: number) => {
39-
const modelInfo = test.config?.model ? ` [Target: ${test.config.provider || 'unknown'}/${test.config.model}]` : '';
40-
console.log(`${index + 1}. ${chalk.bold(test.description)}${chalk.cyan(modelInfo)}`);
41-
console.log(` Score: ${chalk.red(test.score.toFixed(2))} (threshold: ${test.threshold})`);
37+
console.log(chalk.gray(` ${index + 1}. ${test.description} — score: ${chalk.red(test.score.toFixed(2))} / ${test.threshold}`));
4238
});
4339

4440
// Step 3: Ask which tests to fix
4541
let selectedIndexes: number[] = [];
4642
if (options.yes) {
4743
selectedIndexes = failedTests.map((_, i) => i);
48-
console.log(chalk.gray(`\nNon-interactive mode: Automatic selection of all ${failedTests.length} tests.`));
4944
} else {
5045
const response = await inquirer.prompt([{
5146
type: 'checkbox',
5247
name: 'selectedIndexes',
5348
message: 'Which tests would you like to fix?',
54-
choices: failedTests.map((test: FailedTest, index: number) => {
55-
const modelInfo = test.config?.model ? ` [${test.config.provider || 'unknown'}/${test.config.model}]` : '';
56-
return {
57-
name: `${test.description} (score: ${test.score.toFixed(2)})${modelInfo}`,
58-
value: index,
59-
checked: true
60-
};
61-
})
49+
choices: failedTests.map((test: FailedTest, index: number) => ({
50+
name: `${test.description} (${test.score.toFixed(2)})`,
51+
value: index,
52+
checked: true
53+
}))
6254
}]);
6355
selectedIndexes = response.selectedIndexes;
6456
}
@@ -78,8 +70,8 @@ export async function fixCommand(options: { yes?: boolean } = {}) {
7870
const test = failedTests[index];
7971
const suite = await getSuiteTests(test.id);
8072

81-
const modelInfo = test.config?.model ? ` (Target: ${test.config.model})` : '';
82-
console.log(chalk.bold(`\n\n━━━ Fixing: ${test.description}${modelInfo} ━━━\n`));
73+
const modelInfo = test.config?.model ? ` (${test.config.model})` : '';
74+
console.log(chalk.bold(`\n━━━ ${test.description}${modelInfo} ━━━\n`));
8375

8476
try {
8577
const result = await optimizer.optimize(test, suite);
@@ -104,8 +96,7 @@ export async function fixCommand(options: { yes?: boolean } = {}) {
10496

10597
if (action === 'apply') {
10698
await applyFix(test, result.optimizedPrompt);
107-
console.log(`\n${chalk.bgGreen.black(' DONE ')} ${chalk.green('Prompt updated in:')} ${chalk.bold(test.id)}`);
108-
console.log(chalk.gray('The next run will use this new prompt.\n'));
99+
console.log(chalk.green(` ✓ Updated: ${test.id}`));
109100
} else if (action === 'edit') {
110101
console.log(chalk.gray('\nOpening editor... (Save and close to apply)\n'));
111102
const { edited } = await inquirer.prompt([{
@@ -126,8 +117,7 @@ export async function fixCommand(options: { yes?: boolean } = {}) {
126117
}
127118
}
128119

129-
console.log(chalk.bold.green('\n\n✨ Fix session complete!\n'));
130-
console.log(chalk.gray('Run `tuneprompt run` to verify your fixes.\n'));
120+
console.log(chalk.bold.green('\n✨ Done. Run `tuneprompt run` to verify.\n'));
131121

132122
// After fix completes
133123
const license = getLicenseInfo();
@@ -145,20 +135,9 @@ export async function fixCommand(options: { yes?: boolean } = {}) {
145135
}
146136

147137
function showUpgradePrompt() {
148-
console.log(chalk.yellow('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
149-
console.log(chalk.bold('🔒 Premium Feature: Auto-Fix Engine\n'));
150-
console.log('The ' + chalk.cyan('fix') + ' command uses advanced AI to automatically');
151-
console.log('repair your failing prompts.\n');
152-
console.log(chalk.bold('What you get:'));
153-
console.log(' ✅ AI-powered prompt optimization');
154-
console.log(' ✅ Shadow testing before applying fixes');
155-
console.log(' ✅ Interactive diff viewer');
156-
console.log(' ✅ Unlimited fix attempts\n');
157-
158-
console.log(chalk.bold('Get Premium:'));
159-
console.log(` 1. Buy a license: ${chalk.blue.underline('https://www.tuneprompt.xyz/pricing')}`);
160-
console.log(` 2. Activate: ${chalk.gray('tuneprompt activate <your-key>')}\n`);
161-
console.log(chalk.yellow('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'));
138+
console.log(chalk.yellow('\n🔒 Premium feature. Get access:'));
139+
console.log(chalk.gray(` ${chalk.blue.underline('https://www.tuneprompt.xyz/pricing')}`));
140+
console.log(chalk.gray(` Then: ${chalk.white('tuneprompt activate <key>')}\n`));
162141
}
163142

164143
async function showDiff(original: string, optimized: string, reasoning: string) {

src/commands/run.ts

Lines changed: 11 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import { TestLoader } from '../engine/loader';
88
import { TestRunner } from '../engine/runner';
99
import { TestReporter } from '../engine/reporter';
1010
import { TestDatabase } from '../storage/database';
11-
import { LicenseManager, getLicenseInfo } from '../utils/license';
12-
import { TestResult } from '../types';
1311

1412
export interface RunOptions {
1513
config?: string;
@@ -18,48 +16,18 @@ export interface RunOptions {
1816
cloud?: boolean;
1917
}
2018

21-
// At the end of your test run reporter
22-
function displayRunSummary(results: TestResult[]): void {
23-
const failed = results.filter(r => r.status === 'fail');
24-
const passed = results.filter(r => r.status === 'pass');
25-
26-
console.log(chalk.bold.white('\n' + '='.repeat(60)));
27-
console.log(chalk.bold.white('Test Summary'));
28-
console.log(chalk.bold.white('='.repeat(60)));
29-
console.log(chalk.green(`✓ Passed: ${passed.length}`));
30-
console.log(chalk.red(`✗ Failed: ${failed.length}`));
31-
console.log(chalk.gray(`Total: ${results.length}`));
32-
console.log(chalk.bold.white('='.repeat(60) + '\n'));
33-
34-
// UPSELL MESSAGE (NEW)
35-
if (failed.length > 0) {
36-
console.log(chalk.yellow('⚠️ ' + failed.length + ' test(s) failed'));
37-
console.log(chalk.gray('\nDon\'t waste time debugging manually.'));
38-
console.log(chalk.cyan('Run ') + chalk.bold.white('tuneprompt fix') + chalk.cyan(' to let AI repair these prompts instantly.\n'));
39-
40-
// Check license status
41-
const licenseManager = new LicenseManager();
42-
licenseManager.hasFeature('fix').then((hasAccess: boolean) => {
43-
if (!hasAccess) {
44-
console.log(chalk.gray('Unlock fix with: ') + chalk.white('https://www.tuneprompt.xyz/pricing'));
45-
console.log(chalk.gray('Already have a key? ') + chalk.white('tuneprompt activate <key>\n'));
46-
}
47-
});
48-
}
49-
}
19+
5020

5121
// Extract the core run functionality to a separate function
5222
export async function runTests(options: RunOptions = {}) {
5323
const startTime = Date.now();
54-
const spinner = ora('Loading configuration...').start();
24+
const spinner = ora('Loading...').start();
5525

5626
try {
57-
// Load config
5827
const config = await loadConfig(options.config);
5928
spinner.succeed('Configuration loaded');
6029

61-
// Load tests
62-
spinner.start('Loading test cases...');
30+
spinner.start('Loading tests...');
6331
const loader = new TestLoader();
6432
const testCases = loader.loadTestDir(config.testDir || './tests');
6533

@@ -68,23 +36,19 @@ export async function runTests(options: RunOptions = {}) {
6836
process.exit(1);
6937
}
7038

71-
spinner.succeed(`Loaded ${testCases.length} test case(s)`);
39+
spinner.succeed(`Loaded ${testCases.length} test(s)`);
7240

73-
// Run tests
7441
spinner.start('Running tests...');
7542
const runner = new TestRunner(config);
7643
const results = await runner.runTests(testCases);
7744
spinner.stop();
7845

79-
// Save to database
80-
// Save to database
8146
const db = new TestDatabase();
8247
db.saveRun(results);
8348

84-
// Calculate results for cloud upload (and for sync logic)
85-
const currentRunId = results.id; // Assuming results has ID
49+
// Calculate results for cloud upload
50+
const currentRunId = results.id;
8651

87-
// Report results
8852
const reporter = new TestReporter();
8953
reporter.printResults(results, config.outputFormat);
9054

@@ -123,16 +87,15 @@ export const runCommand = new Command('run')
12387

12488
async function syncPendingRuns(db: TestDatabase, options: any) {
12589
const pendingRuns = db.getPendingUploads();
126-
12790
if (pendingRuns.length === 0) return;
12891

129-
console.log(chalk.blue(`\n☁️ Syncing ${pendingRuns.length} pending run(s) to Cloud...`));
92+
const syncSpinner = ora(`Syncing ${pendingRuns.length} run(s) to Cloud...`).start();
13093

13194
const cloudService = new CloudService();
13295
await cloudService.init();
13396

13497
if (!(await cloudService.isAuthenticated())) {
135-
console.log(chalk.yellow('⚠️ Not authenticated. Run `tuneprompt activate` first.'));
98+
syncSpinner.warn('Not authenticated. Run `tuneprompt activate` first.');
13699
return;
137100
}
138101

@@ -147,7 +110,7 @@ async function syncPendingRuns(db: TestDatabase, options: any) {
147110
projectId = projects[0].id;
148111
}
149112
} catch (err) {
150-
console.log(chalk.yellow('⚠️ Failed to get project info'));
113+
syncSpinner.warn('Failed to get project info');
151114
return;
152115
}
153116

@@ -202,9 +165,8 @@ async function syncPendingRuns(db: TestDatabase, options: any) {
202165

203166
if (uploadResult.success) {
204167
db.markAsUploaded(run.id);
205-
console.log(chalk.green(` ✓ Uploaded run from ${run.timestamp.toLocaleTimeString()}`));
206-
} else {
207-
console.log(chalk.red(` ✗ Failed to upload run ${run.id}: ${uploadResult.error}`));
208168
}
209169
}
170+
171+
syncSpinner.succeed(`Synced ${pendingRuns.length} run(s) to Cloud`);
210172
}

src/engine/optimizer.ts

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { FailedTest, OptimizationResult, FixCandidate } from '../types/fix';
2+
import ora from 'ora';
3+
import chalk from 'chalk';
24
import {
35
generateOptimizationPrompt,
46
generateJSONFixPrompt,
@@ -21,11 +23,8 @@ export class PromptOptimizer {
2123
* Main optimization method with Anti-Regression and Iterative Refinement
2224
*/
2325
async optimize(failedTest: FailedTest, suite: FailedTest[]): Promise<OptimizationResult> {
24-
console.log(`\n🧠 Analyzing failure: "${failedTest.description}"`);
25-
console.log(`📈 Full test suite size: ${suite.length}`);
26-
26+
const spinner = ora(`Analyzing failure: "${failedTest.description}"`).start();
2727
const initialAggregateScore = suite.reduce((sum, t) => sum + t.score, 0) / suite.length;
28-
console.log(`📊 Current aggregate score: ${initialAggregateScore.toFixed(2)}`);
2928

3029
const errorContext = generateErrorContext(failedTest);
3130
const passingExamples = suite
@@ -41,7 +40,7 @@ export class PromptOptimizer {
4140

4241
while (iterations < this.maxIterations) {
4342
iterations++;
44-
console.log(`🚀 Optimization Attempt #${iterations}...`);
43+
spinner.text = `Optimization Attempt #${iterations}/${this.maxIterations}...`;
4544

4645
if (iterations === 1) {
4746
const input: MetaPromptInput = {
@@ -67,21 +66,19 @@ export class PromptOptimizer {
6766

6867
for (const candidate of candidates) {
6968
try {
70-
console.log(`🧪 Testing candidate...`);
69+
spinner.text = `Attempt #${iterations}: Testing candidate...`;
7170

7271
const primaryResult = await runShadowTest(candidate.prompt, failedTest);
7372

7473
if (primaryResult.score < failedTest.threshold) {
75-
console.log(` ❌ Candidate failed to resolve primary error (score: ${primaryResult.score.toFixed(2)})`);
76-
const specificReason = primaryResult.failureReason || `the output was: "${primaryResult.output.substring(0, 100)}..."`;
77-
lastFailureReason = `Candidate failed. Reason: ${specificReason}. Previous reasoning: ${candidate.reasoning}`;
74+
const specificReason = primaryResult.failureReason || `the output was: "${primaryResult.output.substring(0, 50)}..."`;
75+
lastFailureReason = `Candidate failed. Reason: ${specificReason}.`;
7876
continue;
7977
}
8078

81-
console.log(` ✅ Resolved primary error. Running anti-regression...`);
79+
spinner.text = `Attempt #${iterations}: Verifying anti-regression...`;
8280

8381
const suiteResult = await runSuiteShadowTest(candidate.prompt, suite);
84-
console.log(` 📊 Suite aggregate score: ${suiteResult.aggregateScore.toFixed(2)}`);
8582

8683
if (suiteResult.aggregateScore > bestAggregateScore) {
8784
bestAggregateScore = suiteResult.aggregateScore;
@@ -99,24 +96,25 @@ export class PromptOptimizer {
9996
iterations
10097
};
10198
} else if (suiteResult.aggregateScore <= bestAggregateScore) {
102-
console.log(` 📉 Candidate regression: aggregate score dropped (Current: ${bestAggregateScore.toFixed(2)} VS New: ${suiteResult.aggregateScore.toFixed(2)})`);
10399
const regressions = suiteResult.results.filter(r => !r.passed).map(r => r.failureReason).filter(Boolean);
104100
const regressionText = regressions.length > 0 ? ` Required features broke: ${regressions.slice(0, 2).join('; ')}.` : '';
105-
lastFailureReason = `The fix resolved the failure but introduced regressions in other cases.${regressionText} Maintain all successful patterns while fixing the failure.`;
101+
lastFailureReason = `Fix introduced regressions.${regressionText}`;
106102
}
107103
} catch (error: any) {
108-
console.error(` ⚠️ Validation error for candidate: ${error.message}`);
104+
spinner.text = `Attempt #${iterations}: ⚠️ ${error.message?.substring(0, 80)}`;
105+
lastFailureReason = error.message;
109106
}
110107
}
111108

112109
if (bestResult) break;
113-
console.log(`♻️ No candidate was net-positive. Retrying with refinement feedback...`);
114110
}
115111

116112
if (!bestResult) {
117-
throw new Error(`All fix attempts failed to resolve the regression or improve the aggregate score after ${this.maxIterations} iterations.`);
113+
spinner.fail(`Optimization failed`);
114+
throw new Error(`Failed to improve score after ${this.maxIterations} attempts. ${lastFailureReason || ''}`);
118115
}
119116

117+
spinner.succeed(`Optimization successful!`);
120118
return bestResult;
121119
}
122120

src/engine/reporter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import Table from 'cli-table3';
33
import { TestRun, TestResult } from '../types';
44

55
export class TestReporter {
6-
printResults(run: TestRun, format: 'json' | 'table' | 'both' = 'both') {
6+
printResults(run: TestRun, format: 'json' | 'table' | 'both' = 'table') {
77
if (format === 'json' || format === 'both') {
88
this.printJSON(run);
99
}

src/engine/shadowTester.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,10 @@ export async function runShadowTest(
6767
for (const target of providersToTry) {
6868
try {
6969
const apiKey = ProviderFactory.getApiKey(target.name);
70-
if (!apiKey) continue;
70+
if (!apiKey) {
71+
errors.push(`${target.name}: no API key (set ${target.name.toUpperCase()}_API_KEY)`);
72+
continue;
73+
}
7174

7275
const provider = ProviderFactory.create(target.name, {
7376
apiKey,

src/utils/config.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ function validateConfig(config: any): TunePromptConfig {
3939
return {
4040
threshold: config.threshold || 0.8,
4141
testDir: config.testDir || './tests',
42-
outputFormat: config.outputFormat || 'both',
42+
outputFormat: config.outputFormat || 'table',
4343
...config
4444
};
4545
}
@@ -80,7 +80,7 @@ export function getDefaultConfigTemplate(): string {
8080
testDir: './tests',
8181
8282
// Output format: 'json', 'table', or 'both'
83-
outputFormat: 'both'
83+
outputFormat: 'table'
8484
};
8585
`;
8686
}

tuneprompt.config.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ module.exports = {
2525
temperature: 0.7
2626
}
2727
},
28-
28+
2929
// Global semantic similarity threshold
3030
threshold: 0.8,
31-
31+
3232
// Directory containing test files
3333
testDir: './tests',
34-
34+
3535
// Output format: 'json', 'table', or 'both'
36-
outputFormat: 'both'
36+
outputFormat: 'table'
3737
};

0 commit comments

Comments
 (0)