tuneprompt 1.0.6 → 1.0.7
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/dist/commands/init.js
CHANGED
|
@@ -91,9 +91,6 @@ async function initCommand() {
|
|
|
91
91
|
const envContent = `OPENAI_API_KEY=your_key_here
|
|
92
92
|
ANTHROPIC_API_KEY=your_key_here
|
|
93
93
|
OPENROUTER_API_KEY=your_key_here
|
|
94
|
-
|
|
95
|
-
# For self-hosted or local testing:
|
|
96
|
-
# TUNEPROMPT_API_URL=http://localhost:3000
|
|
97
94
|
`;
|
|
98
95
|
fs.writeFileSync(envPath, envContent);
|
|
99
96
|
console.log(chalk_1.default.green('✓ Created .env'));
|
package/dist/engine/optimizer.js
CHANGED
|
@@ -44,19 +44,34 @@ const constraintExtractor_1 = require("./constraintExtractor");
|
|
|
44
44
|
class PromptOptimizer {
|
|
45
45
|
anthropic;
|
|
46
46
|
openai;
|
|
47
|
+
openrouter;
|
|
47
48
|
constructor() {
|
|
48
49
|
const anthropicKey = process.env.ANTHROPIC_API_KEY;
|
|
49
|
-
if (anthropicKey &&
|
|
50
|
+
if (anthropicKey &&
|
|
51
|
+
!anthropicKey.includes('your_key') &&
|
|
52
|
+
!anthropicKey.startsWith('api_key') &&
|
|
53
|
+
anthropicKey !== 'phc_xxxxx') {
|
|
50
54
|
this.anthropic = new sdk_1.default({
|
|
51
55
|
apiKey: anthropicKey
|
|
52
56
|
});
|
|
53
57
|
}
|
|
54
58
|
const openaiKey = process.env.OPENAI_API_KEY;
|
|
55
|
-
if (openaiKey && !openaiKey.
|
|
59
|
+
if (openaiKey && !openaiKey.includes('your_key')) {
|
|
56
60
|
this.openai = new openai_1.default({
|
|
57
61
|
apiKey: openaiKey
|
|
58
62
|
});
|
|
59
63
|
}
|
|
64
|
+
const openrouterKey = process.env.OPENROUTER_API_KEY;
|
|
65
|
+
if (openrouterKey && !openrouterKey.includes('your_key')) {
|
|
66
|
+
this.openrouter = new openai_1.default({
|
|
67
|
+
baseURL: 'https://openrouter.ai/api/v1',
|
|
68
|
+
apiKey: openrouterKey,
|
|
69
|
+
defaultHeaders: {
|
|
70
|
+
'HTTP-Referer': 'https://tuneprompt.xyz',
|
|
71
|
+
'X-Title': 'TunePrompt CLI',
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
}
|
|
60
75
|
}
|
|
61
76
|
/**
|
|
62
77
|
* Main optimization method
|
|
@@ -118,7 +133,7 @@ class PromptOptimizer {
|
|
|
118
133
|
if (provider === 'anthropic' && this.anthropic) {
|
|
119
134
|
console.log(`⚡ Using Anthropic for candidate generation...`);
|
|
120
135
|
const response = await this.anthropic.messages.create({
|
|
121
|
-
model: 'claude-sonnet-
|
|
136
|
+
model: 'claude-3-5-sonnet-20240620',
|
|
122
137
|
max_tokens: 4000,
|
|
123
138
|
temperature: 0.7, // Some creativity for prompt rewriting
|
|
124
139
|
messages: [{
|
|
@@ -174,16 +189,34 @@ class PromptOptimizer {
|
|
|
174
189
|
}
|
|
175
190
|
];
|
|
176
191
|
}
|
|
177
|
-
else if (provider === 'openrouter') {
|
|
178
|
-
// For OpenRouter, we'll use the shadowTester to get a response
|
|
192
|
+
else if (provider === 'openrouter' && this.openrouter) {
|
|
179
193
|
console.log(`⚡ Using OpenRouter for candidate generation...`);
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
194
|
+
const response = await this.openrouter.chat.completions.create({
|
|
195
|
+
model: 'anthropic/claude-3-sonnet', // Default robust model on OpenRouter
|
|
196
|
+
messages: [{
|
|
197
|
+
role: 'user',
|
|
198
|
+
content: metaPrompt
|
|
199
|
+
}],
|
|
200
|
+
response_format: { type: 'json_object' }
|
|
201
|
+
});
|
|
202
|
+
const content = response.choices[0]?.message?.content;
|
|
203
|
+
if (!content) {
|
|
204
|
+
// Fallback if model doesn't support JSON mode or returns empty
|
|
205
|
+
throw new Error('No content returned from OpenRouter');
|
|
206
|
+
}
|
|
207
|
+
const parsed = JSON.parse(content);
|
|
208
|
+
return [
|
|
209
|
+
{
|
|
210
|
+
prompt: parsed.candidateA.prompt,
|
|
211
|
+
reasoning: parsed.candidateA.reasoning,
|
|
185
212
|
score: 0
|
|
186
|
-
}
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
prompt: parsed.candidateB.prompt,
|
|
216
|
+
reasoning: parsed.candidateB.reasoning,
|
|
217
|
+
score: 0
|
|
218
|
+
}
|
|
219
|
+
];
|
|
187
220
|
}
|
|
188
221
|
}
|
|
189
222
|
catch (error) {
|
|
@@ -195,7 +228,7 @@ class PromptOptimizer {
|
|
|
195
228
|
console.error('All providers failed for candidate generation');
|
|
196
229
|
return [{
|
|
197
230
|
prompt: this.createFallbackPrompt(failedTest),
|
|
198
|
-
reasoning: '
|
|
231
|
+
reasoning: 'Generated using fallback method',
|
|
199
232
|
score: 0
|
|
200
233
|
}];
|
|
201
234
|
}
|
|
@@ -10,7 +10,7 @@ class CloudService {
|
|
|
10
10
|
backendUrl;
|
|
11
11
|
subscriptionId;
|
|
12
12
|
constructor() {
|
|
13
|
-
this.backendUrl = process.env.TUNEPROMPT_API_URL || process.env.BACKEND_URL || 'https://api.
|
|
13
|
+
this.backendUrl = process.env.TUNEPROMPT_API_URL || process.env.BACKEND_URL || 'https://i8e3mu8jlk.execute-api.ap-south-1.amazonaws.com/dev';
|
|
14
14
|
}
|
|
15
15
|
async init() {
|
|
16
16
|
// Load subscription ID from local storage (Phase 2 activation)
|
|
@@ -21,9 +21,16 @@ class CloudService {
|
|
|
21
21
|
return license?.subscriptionId;
|
|
22
22
|
}
|
|
23
23
|
async uploadRun(data) {
|
|
24
|
-
|
|
24
|
+
// Enforce Pro plan check
|
|
25
|
+
const license = (0, license_1.loadLicense)();
|
|
26
|
+
if (!this.subscriptionId || !license) {
|
|
25
27
|
return { success: false, error: 'Not activated. Run `tuneprompt activate` first.' };
|
|
26
28
|
}
|
|
29
|
+
// Check for specific pro plans (if we ever add free tiers)
|
|
30
|
+
const proPlans = ['pro-monthly', 'pro-yearly', 'lifetime'];
|
|
31
|
+
if (!proPlans.includes(license.plan)) {
|
|
32
|
+
return { success: false, error: 'Cloud features are restricted to Pro users. Please upgrade your plan.' };
|
|
33
|
+
}
|
|
27
34
|
try {
|
|
28
35
|
const response = await axios_1.default.post(`${this.backendUrl}/api/cloud/ingest-run`, data, {
|
|
29
36
|
headers: {
|
package/dist/storage/database.js
CHANGED
|
@@ -93,9 +93,13 @@ class TestDatabase {
|
|
|
93
93
|
}
|
|
94
94
|
catch (e) {
|
|
95
95
|
// Column might already exist
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
96
|
+
}
|
|
97
|
+
// Migration for provider column
|
|
98
|
+
try {
|
|
99
|
+
this.db.exec(`ALTER TABLE test_results ADD COLUMN provider TEXT`);
|
|
100
|
+
}
|
|
101
|
+
catch (e) {
|
|
102
|
+
// Column might already exist
|
|
99
103
|
}
|
|
100
104
|
// Run external migrations (Phase 2)
|
|
101
105
|
(0, migrate_1.runMigrations)(this.db).catch((err) => {
|
|
@@ -110,11 +114,11 @@ class TestDatabase {
|
|
|
110
114
|
insertRun.run(run.id, run.timestamp.getTime(), run.totalTests, run.passed, run.failed, run.duration);
|
|
111
115
|
const insertResult = this.db.prepare(`
|
|
112
116
|
INSERT INTO test_results
|
|
113
|
-
(id, run_id, description, prompt, variables, expect, config, file_path, status, score, actual_output, expected_output, error, duration, tokens, cost)
|
|
114
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
117
|
+
(id, run_id, description, prompt, variables, expect, config, file_path, status, score, actual_output, expected_output, error, duration, tokens, cost, provider)
|
|
118
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
115
119
|
`);
|
|
116
120
|
for (const result of run.results) {
|
|
117
|
-
insertResult.run(result.id, run.id, result.testCase.description, typeof result.testCase.prompt === 'string' ? result.testCase.prompt : JSON.stringify(result.testCase.prompt), result.testCase.variables ? JSON.stringify(result.testCase.variables) : null, typeof result.testCase.expect === 'string' ? result.testCase.expect : JSON.stringify(result.testCase.expect), result.testCase.config ? JSON.stringify(result.testCase.config) : null, result.testCase.filePath || null, result.status, result.score, result.actualOutput, result.expectedOutput, result.error || null, result.metadata.duration, result.metadata.tokens || null, result.metadata.cost || null);
|
|
121
|
+
insertResult.run(result.id, run.id, result.testCase.description, typeof result.testCase.prompt === 'string' ? result.testCase.prompt : JSON.stringify(result.testCase.prompt), result.testCase.variables ? JSON.stringify(result.testCase.variables) : null, typeof result.testCase.expect === 'string' ? result.testCase.expect : JSON.stringify(result.testCase.expect), result.testCase.config ? JSON.stringify(result.testCase.config) : null, result.testCase.filePath || null, result.status, result.score, result.actualOutput, result.expectedOutput, result.error || null, result.metadata.duration, result.metadata.tokens || null, result.metadata.cost || null, result.metadata.provider || null);
|
|
118
122
|
}
|
|
119
123
|
}
|
|
120
124
|
getRecentRuns(limit = 10) {
|
|
@@ -194,7 +198,8 @@ class TestDatabase {
|
|
|
194
198
|
duration: r.duration,
|
|
195
199
|
timestamp: new Date(),
|
|
196
200
|
tokens: r.tokens,
|
|
197
|
-
cost: r.cost
|
|
201
|
+
cost: r.cost,
|
|
202
|
+
provider: r.provider
|
|
198
203
|
}
|
|
199
204
|
};
|
|
200
205
|
});
|