prpm 0.1.11 โ 0.1.13
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/collections.js +19 -7
- package/dist/commands/install.js +19 -8
- package/dist/commands/playground.js +240 -20
- package/dist/commands/uninstall.js +29 -45
- package/package.json +3 -3
|
@@ -87,7 +87,9 @@ async function handleCollectionsSearch(query, options) {
|
|
|
87
87
|
if (c.description) {
|
|
88
88
|
console.log(` ${c.description.substring(0, 70)}${c.description.length > 70 ? '...' : ''}`);
|
|
89
89
|
}
|
|
90
|
-
|
|
90
|
+
if (c.author) {
|
|
91
|
+
console.log(` ๐ค by @${c.author}${c.verified ? ' โ' : ''}`);
|
|
92
|
+
}
|
|
91
93
|
console.log(` โฌ๏ธ ${c.downloads.toLocaleString()} installs ยท โญ ${c.stars.toLocaleString()} stars`);
|
|
92
94
|
console.log('');
|
|
93
95
|
});
|
|
@@ -101,7 +103,9 @@ async function handleCollectionsSearch(query, options) {
|
|
|
101
103
|
if (c.description) {
|
|
102
104
|
console.log(` ${c.description.substring(0, 70)}${c.description.length > 70 ? '...' : ''}`);
|
|
103
105
|
}
|
|
104
|
-
|
|
106
|
+
if (c.author) {
|
|
107
|
+
console.log(` ๐ค by @${c.author}${c.verified ? ' โ' : ''}`);
|
|
108
|
+
}
|
|
105
109
|
console.log(` โฌ๏ธ ${c.downloads.toLocaleString()} installs ยท โญ ${c.stars.toLocaleString()} stars`);
|
|
106
110
|
console.log('');
|
|
107
111
|
});
|
|
@@ -169,7 +173,9 @@ async function handleCollectionsList(options) {
|
|
|
169
173
|
if (c.description) {
|
|
170
174
|
console.log(` ${c.description.substring(0, 70)}${c.description.length > 70 ? '...' : ''}`);
|
|
171
175
|
}
|
|
172
|
-
|
|
176
|
+
if (c.author) {
|
|
177
|
+
console.log(` ๐ค by @${c.author}${c.verified ? ' โ' : ''}`);
|
|
178
|
+
}
|
|
173
179
|
console.log(` โฌ๏ธ ${c.downloads.toLocaleString()} installs ยท โญ ${c.stars.toLocaleString()} stars`);
|
|
174
180
|
console.log('');
|
|
175
181
|
});
|
|
@@ -183,7 +189,9 @@ async function handleCollectionsList(options) {
|
|
|
183
189
|
if (c.description) {
|
|
184
190
|
console.log(` ${c.description.substring(0, 70)}${c.description.length > 70 ? '...' : ''}`);
|
|
185
191
|
}
|
|
186
|
-
|
|
192
|
+
if (c.author) {
|
|
193
|
+
console.log(` ๐ค by @${c.author}${c.verified ? ' โ' : ''}`);
|
|
194
|
+
}
|
|
187
195
|
console.log(` โฌ๏ธ ${c.downloads.toLocaleString()} installs ยท โญ ${c.stars.toLocaleString()} stars`);
|
|
188
196
|
console.log('');
|
|
189
197
|
});
|
|
@@ -265,7 +273,9 @@ async function handleCollectionInfo(collectionSpec) {
|
|
|
265
273
|
console.log(` Stars: ${collection.stars.toLocaleString()}`);
|
|
266
274
|
console.log(` Version: ${collection.version}`);
|
|
267
275
|
console.log(` Packages: ${collection.packages.length}`);
|
|
268
|
-
|
|
276
|
+
if (collection.author) {
|
|
277
|
+
console.log(` Author: ${collection.author}${collection.verified ? ' โ' : ''}`);
|
|
278
|
+
}
|
|
269
279
|
if (collection.category) {
|
|
270
280
|
console.log(` Category: ${collection.category}`);
|
|
271
281
|
}
|
|
@@ -503,8 +513,10 @@ async function handleCollectionInstall(collectionSpec, options) {
|
|
|
503
513
|
try {
|
|
504
514
|
console.log(`\n ${progress} Installing ${pkg.packageId}@${pkg.version}...`);
|
|
505
515
|
// Only pass 'as' format if user explicitly requested it via --as flag
|
|
506
|
-
// Otherwise,
|
|
507
|
-
//
|
|
516
|
+
// Otherwise, handleInstall will use this priority order:
|
|
517
|
+
// 1. defaultFormat from .prpmrc config
|
|
518
|
+
// 2. Auto-detection based on existing directories
|
|
519
|
+
// 3. Package native format
|
|
508
520
|
const installOptions = {
|
|
509
521
|
fromCollection: {
|
|
510
522
|
scope,
|
package/dist/commands/install.js
CHANGED
|
@@ -224,18 +224,29 @@ async function handleInstall(packageSpec, options) {
|
|
|
224
224
|
console.log(` ${pkg.name} ${pkg.official ? '๐
' : ''}`);
|
|
225
225
|
console.log(` ${pkg.description || 'No description'}`);
|
|
226
226
|
console.log(` ${typeIcon} Type: ${typeLabel}`);
|
|
227
|
-
// Determine format preference with
|
|
227
|
+
// Determine format preference with priority order:
|
|
228
|
+
// 1. CLI --as flag (highest priority)
|
|
229
|
+
// 2. defaultFormat from .prpmrc config
|
|
230
|
+
// 3. Auto-detection based on existing directories
|
|
231
|
+
// 4. Package native format (fallback)
|
|
228
232
|
let format = options.as;
|
|
229
|
-
// Auto-detect format if not explicitly specified
|
|
230
233
|
if (!format) {
|
|
231
|
-
|
|
232
|
-
if (
|
|
233
|
-
format =
|
|
234
|
-
console.log(`
|
|
234
|
+
// Check for config default format
|
|
235
|
+
if (config.defaultFormat) {
|
|
236
|
+
format = config.defaultFormat;
|
|
237
|
+
console.log(` โ๏ธ Using default format from config: ${format}`);
|
|
235
238
|
}
|
|
236
239
|
else {
|
|
237
|
-
//
|
|
238
|
-
|
|
240
|
+
// Auto-detect format based on existing directories
|
|
241
|
+
const detectedFormat = await (0, filesystem_1.autoDetectFormat)();
|
|
242
|
+
if (detectedFormat) {
|
|
243
|
+
format = detectedFormat;
|
|
244
|
+
console.log(` ๐ Auto-detected ${format} format (found .${format}/ directory)`);
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
// No config or detection, use package's native format
|
|
248
|
+
format = pkg.format;
|
|
249
|
+
}
|
|
239
250
|
}
|
|
240
251
|
}
|
|
241
252
|
// Special handling for Claude packages: default to CLAUDE.md if it doesn't exist
|
|
@@ -42,6 +42,8 @@ const commander_1 = require("commander");
|
|
|
42
42
|
const user_config_1 = require("../core/user-config");
|
|
43
43
|
const telemetry_1 = require("../core/telemetry");
|
|
44
44
|
const readline = __importStar(require("readline"));
|
|
45
|
+
const fs = __importStar(require("fs"));
|
|
46
|
+
const path = __importStar(require("path"));
|
|
45
47
|
const errors_1 = require("../core/errors");
|
|
46
48
|
/**
|
|
47
49
|
* Create a readline interface for user input
|
|
@@ -126,6 +128,28 @@ async function runPlayground(packageName, input, options, sessionId) {
|
|
|
126
128
|
});
|
|
127
129
|
return response.json();
|
|
128
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Execute a custom prompt playground run
|
|
133
|
+
*/
|
|
134
|
+
async function runCustomPrompt(customPrompt, input, options, sessionId) {
|
|
135
|
+
const response = await apiCall('/api/v1/custom-prompt/run', 'POST', {
|
|
136
|
+
custom_prompt: customPrompt,
|
|
137
|
+
input,
|
|
138
|
+
model: options.model || 'sonnet',
|
|
139
|
+
session_id: sessionId,
|
|
140
|
+
});
|
|
141
|
+
return response.json();
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Read custom prompt from file
|
|
145
|
+
*/
|
|
146
|
+
function readPromptFile(filePath) {
|
|
147
|
+
const absolutePath = path.resolve(filePath);
|
|
148
|
+
if (!fs.existsSync(absolutePath)) {
|
|
149
|
+
throw new Error(`Prompt file not found: ${filePath}`);
|
|
150
|
+
}
|
|
151
|
+
return fs.readFileSync(absolutePath, 'utf-8');
|
|
152
|
+
}
|
|
129
153
|
/**
|
|
130
154
|
* Format and display playground response
|
|
131
155
|
*/
|
|
@@ -200,6 +224,139 @@ async function runInteractive(packageName, options) {
|
|
|
200
224
|
rl.close();
|
|
201
225
|
}
|
|
202
226
|
}
|
|
227
|
+
/**
|
|
228
|
+
* Run interactive custom prompt session
|
|
229
|
+
*/
|
|
230
|
+
async function runCustomInteractive(customPrompt, options) {
|
|
231
|
+
console.log('\n๐ฎ Interactive Custom Prompt Mode');
|
|
232
|
+
console.log(` Model: ${options.model || 'sonnet'}`);
|
|
233
|
+
console.log(` Type 'exit' or 'quit' to end session\n`);
|
|
234
|
+
const rl = createReadline();
|
|
235
|
+
let sessionId;
|
|
236
|
+
let turnCount = 0;
|
|
237
|
+
try {
|
|
238
|
+
while (true) {
|
|
239
|
+
const input = await prompt(rl, `\n๐ฌ You: `);
|
|
240
|
+
if (input.trim().toLowerCase() === 'exit' || input.trim().toLowerCase() === 'quit') {
|
|
241
|
+
console.log('\n๐ Ending playground session. Goodbye!');
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
if (!input.trim()) {
|
|
245
|
+
console.log('โ Please enter a message');
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
try {
|
|
249
|
+
console.log('\nโณ Processing...');
|
|
250
|
+
const result = await runCustomPrompt(customPrompt, input, options, sessionId);
|
|
251
|
+
// Store session ID for conversation continuity
|
|
252
|
+
sessionId = result.session_id;
|
|
253
|
+
turnCount++;
|
|
254
|
+
displayResponse(result, true);
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
console.error(`\nโ Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
258
|
+
if (error instanceof Error && error.message.includes('Insufficient credits')) {
|
|
259
|
+
console.log('\n๐ก Get more credits:');
|
|
260
|
+
console.log(' - Purchase credits: prpm buy-credits');
|
|
261
|
+
console.log(' - Subscribe to PRPM+: prpm subscribe');
|
|
262
|
+
console.log(' - Check balance: prpm credits');
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
if (turnCount > 0) {
|
|
268
|
+
console.log(`\n๐ Session summary: ${turnCount} turn(s)`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
finally {
|
|
272
|
+
rl.close();
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Run baseline (no prompt) comparison
|
|
277
|
+
*/
|
|
278
|
+
async function runBaseline(input, options) {
|
|
279
|
+
// Use a minimal package but with use_no_prompt flag to get raw model baseline
|
|
280
|
+
// We need any valid package ID because the API requires it, but the prompt will be ignored
|
|
281
|
+
// Let's use a well-known minimal package (we'll search for any package)
|
|
282
|
+
const config = await (0, user_config_1.getConfig)();
|
|
283
|
+
const baseUrl = (config.registryUrl || "https://registry.prpm.dev").replace(/\/$/, '');
|
|
284
|
+
// Get any package to use for baseline comparison (the prompt will be ignored anyway)
|
|
285
|
+
const searchResponse = await fetch(`${baseUrl}/api/v1/search?q=coding&limit=1`);
|
|
286
|
+
if (!searchResponse.ok) {
|
|
287
|
+
throw new Error('Failed to find a package for baseline comparison');
|
|
288
|
+
}
|
|
289
|
+
const searchData = await searchResponse.json();
|
|
290
|
+
if (!searchData.packages || searchData.packages.length === 0) {
|
|
291
|
+
throw new Error('No packages found for baseline comparison');
|
|
292
|
+
}
|
|
293
|
+
const dummyPackageId = searchData.packages[0].id;
|
|
294
|
+
// Call playground with use_no_prompt flag (this ignores the package prompt)
|
|
295
|
+
const response = await apiCall('/api/v1/playground/run', 'POST', {
|
|
296
|
+
package_id: dummyPackageId,
|
|
297
|
+
input,
|
|
298
|
+
model: options.model || 'sonnet',
|
|
299
|
+
use_no_prompt: true, // This makes it a raw baseline with no system prompt
|
|
300
|
+
});
|
|
301
|
+
return response.json();
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Run single custom prompt query
|
|
305
|
+
*/
|
|
306
|
+
async function runCustomSingle(customPrompt, input, options) {
|
|
307
|
+
console.log(`\n๐ฎ Testing custom prompt`);
|
|
308
|
+
console.log(` Model: ${options.model || 'sonnet'}`);
|
|
309
|
+
console.log(` Credits: 2x normal cost (custom prompts)`);
|
|
310
|
+
if (options.compare) {
|
|
311
|
+
console.log(` Mode: Comparing custom prompt vs. no prompt (baseline)`);
|
|
312
|
+
}
|
|
313
|
+
try {
|
|
314
|
+
if (options.compare) {
|
|
315
|
+
// Comparison mode: run with custom prompt and without any prompt
|
|
316
|
+
console.log('\nโณ Processing comparison (2 requests)...');
|
|
317
|
+
// Run with custom prompt
|
|
318
|
+
const resultWithPrompt = await runCustomPrompt(customPrompt, input, options);
|
|
319
|
+
// Run baseline (no prompt at all)
|
|
320
|
+
const resultBaseline = await runBaseline(input, options);
|
|
321
|
+
// Display both results
|
|
322
|
+
console.log('\n' + 'โ'.repeat(60));
|
|
323
|
+
console.log('โจ WITH CUSTOM PROMPT');
|
|
324
|
+
console.log('โ'.repeat(60));
|
|
325
|
+
displayResponse(resultWithPrompt, false);
|
|
326
|
+
console.log('\n' + 'โ'.repeat(60));
|
|
327
|
+
console.log('๐ต WITHOUT PROMPT (BASELINE)');
|
|
328
|
+
console.log('โ'.repeat(60));
|
|
329
|
+
displayResponse(resultBaseline, false);
|
|
330
|
+
// Combined stats
|
|
331
|
+
console.log(`\n๐ Combined Stats:`);
|
|
332
|
+
console.log(` Total tokens: ${resultWithPrompt.tokens_used + resultBaseline.tokens_used}`);
|
|
333
|
+
console.log(` Total credits: ${resultWithPrompt.credits_spent + resultBaseline.credits_spent}`);
|
|
334
|
+
console.log(` Credits remaining: ${resultBaseline.credits_remaining}`);
|
|
335
|
+
console.log(`\n๐ก Compare the responses to evaluate your custom prompt's effectiveness!`);
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
// Single mode: run with custom prompt only
|
|
339
|
+
console.log('\nโณ Processing...');
|
|
340
|
+
const result = await runCustomPrompt(customPrompt, input, options);
|
|
341
|
+
displayResponse(result, true);
|
|
342
|
+
console.log(`\n๐ก Tips:`);
|
|
343
|
+
console.log(` - Use --interactive for multi-turn conversation`);
|
|
344
|
+
console.log(` - Use --compare to test against baseline (no prompt)`);
|
|
345
|
+
console.log(` - Use --prompt-file to iterate on a prompt file`);
|
|
346
|
+
console.log(` - Custom prompts cost 2x credits (no caching)`);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
catch (error) {
|
|
350
|
+
console.error(`\nโ Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
351
|
+
if (error instanceof Error && error.message.includes('Insufficient credits')) {
|
|
352
|
+
console.log('\n๐ก Get more credits:');
|
|
353
|
+
console.log(' - Purchase credits: prpm buy-credits');
|
|
354
|
+
console.log(' - Subscribe to PRPM+: prpm subscribe');
|
|
355
|
+
console.log(' - Check balance: prpm credits');
|
|
356
|
+
}
|
|
357
|
+
throw new errors_1.CLIError(`\nโ Error: ${error instanceof Error ? error.message : String(error)}`, 1);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
203
360
|
/**
|
|
204
361
|
* Run single playground query
|
|
205
362
|
*/
|
|
@@ -259,10 +416,11 @@ async function runSingle(packageName, input, options) {
|
|
|
259
416
|
/**
|
|
260
417
|
* Handle the playground command
|
|
261
418
|
*/
|
|
262
|
-
async function handlePlayground(
|
|
419
|
+
async function handlePlayground(options) {
|
|
263
420
|
const startTime = Date.now();
|
|
264
421
|
let success = false;
|
|
265
422
|
let error;
|
|
423
|
+
let customPromptMode = false;
|
|
266
424
|
try {
|
|
267
425
|
// Validate authentication
|
|
268
426
|
const config = await (0, user_config_1.getConfig)();
|
|
@@ -272,14 +430,50 @@ async function handlePlayground(packageName, input, options) {
|
|
|
272
430
|
console.log(' prpm login');
|
|
273
431
|
throw new errors_1.CLIError('โ Authentication required', 1);
|
|
274
432
|
}
|
|
275
|
-
//
|
|
276
|
-
if (options.
|
|
277
|
-
|
|
278
|
-
|
|
433
|
+
// Check for custom prompt mode
|
|
434
|
+
if (options.custom || options.promptFile) {
|
|
435
|
+
customPromptMode = true;
|
|
436
|
+
// Get custom prompt from option or file
|
|
437
|
+
let customPrompt;
|
|
438
|
+
if (options.promptFile) {
|
|
439
|
+
console.log(`๐ Loading prompt from: ${options.promptFile}`);
|
|
440
|
+
customPrompt = readPromptFile(options.promptFile);
|
|
441
|
+
console.log(`โ
Loaded ${customPrompt.length} characters\n`);
|
|
442
|
+
}
|
|
443
|
+
else {
|
|
444
|
+
customPrompt = options.custom;
|
|
445
|
+
}
|
|
446
|
+
// Validate custom prompt length
|
|
447
|
+
if (customPrompt.length < 10) {
|
|
448
|
+
throw new Error('Custom prompt too short (minimum 10 characters)');
|
|
449
|
+
}
|
|
450
|
+
if (customPrompt.length > 50000) {
|
|
451
|
+
throw new Error('Custom prompt too long (maximum 50000 characters)');
|
|
452
|
+
}
|
|
453
|
+
// Interactive mode or single query
|
|
454
|
+
if (options.interactive || !options.input) {
|
|
455
|
+
// Interactive mode with custom prompt
|
|
456
|
+
await runCustomInteractive(customPrompt, options);
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
// Single query mode with custom prompt
|
|
460
|
+
await runCustomSingle(customPrompt, options.input, options);
|
|
461
|
+
}
|
|
279
462
|
}
|
|
280
463
|
else {
|
|
281
|
-
//
|
|
282
|
-
|
|
464
|
+
// Regular package-based playground
|
|
465
|
+
if (!options.package) {
|
|
466
|
+
throw new Error('Either --package or --custom/--prompt-file is required');
|
|
467
|
+
}
|
|
468
|
+
// Interactive mode or single query
|
|
469
|
+
if (options.interactive || !options.input) {
|
|
470
|
+
// Interactive mode
|
|
471
|
+
await runInteractive(options.package, options);
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
// Single query mode
|
|
475
|
+
await runSingle(options.package, options.input, options);
|
|
476
|
+
}
|
|
283
477
|
}
|
|
284
478
|
success = true;
|
|
285
479
|
}
|
|
@@ -295,10 +489,11 @@ async function handlePlayground(packageName, input, options) {
|
|
|
295
489
|
error,
|
|
296
490
|
duration: Date.now() - startTime,
|
|
297
491
|
data: {
|
|
298
|
-
packageName,
|
|
492
|
+
packageName: customPromptMode ? 'custom-prompt' : (options.package || 'unknown'),
|
|
299
493
|
model: options.model || 'sonnet',
|
|
300
494
|
compare: options.compare || false,
|
|
301
495
|
interactive: options.interactive || false,
|
|
496
|
+
customPrompt: customPromptMode,
|
|
302
497
|
},
|
|
303
498
|
});
|
|
304
499
|
await telemetry_1.telemetry.shutdown();
|
|
@@ -310,30 +505,49 @@ async function handlePlayground(packageName, input, options) {
|
|
|
310
505
|
function createPlaygroundCommand() {
|
|
311
506
|
const command = new commander_1.Command('playground');
|
|
312
507
|
command
|
|
313
|
-
.description('Test a package with AI models in the playground')
|
|
314
|
-
.
|
|
315
|
-
.
|
|
508
|
+
.description('Test a package or custom prompt with AI models in the playground')
|
|
509
|
+
.option('-p, --package <name>', 'Package name to test')
|
|
510
|
+
.option('--input <text>', 'Input text to send to the model (omit for interactive mode)')
|
|
316
511
|
.option('-m, --model <model>', 'AI model to use (sonnet, opus, gpt-4o, gpt-4o-mini, gpt-4-turbo)', 'sonnet')
|
|
317
512
|
.option('-c, --compare', 'Compare against no prompt (test raw model baseline)', false)
|
|
318
513
|
.option('-i, --interactive', 'Start interactive multi-turn conversation mode', false)
|
|
319
514
|
.option('-v, --version <version>', 'Specific package version to test')
|
|
515
|
+
.option('--custom <prompt>', 'Use a custom prompt string (verified authors only)')
|
|
516
|
+
.option('--prompt-file <file>', 'Load custom prompt from a file (verified authors only)')
|
|
320
517
|
.addHelpText('after', `
|
|
321
518
|
Examples:
|
|
322
|
-
#
|
|
323
|
-
$ prpm playground @anthropic/code-reviewer "Review this code: console.log('hello')"
|
|
519
|
+
# Test a package (single query)
|
|
520
|
+
$ prpm playground --package @anthropic/code-reviewer --input "Review this code: console.log('hello')"
|
|
324
521
|
|
|
325
522
|
# Interactive mode for multi-turn conversation
|
|
326
|
-
$ prpm playground @anthropic/brainstorm-assistant --interactive
|
|
523
|
+
$ prpm playground --package @anthropic/brainstorm-assistant --interactive
|
|
327
524
|
|
|
328
525
|
# Compare with and without the package prompt
|
|
329
|
-
$ prpm playground @user/custom-prompt "Test input" --compare
|
|
526
|
+
$ prpm playground --package @user/custom-prompt --input "Test input" --compare
|
|
330
527
|
|
|
331
528
|
# Use a different model
|
|
332
|
-
$ prpm playground @user/prompt --model opus "Complex task requiring Opus"
|
|
333
|
-
$ prpm playground @user/prompt --model gpt-4o "Test with GPT-4o"
|
|
529
|
+
$ prpm playground --package @user/prompt --model opus --input "Complex task requiring Opus"
|
|
530
|
+
$ prpm playground --package @user/prompt --model gpt-4o --input "Test with GPT-4o"
|
|
334
531
|
|
|
335
532
|
# Test specific version
|
|
336
|
-
$ prpm playground @user/prompt
|
|
533
|
+
$ prpm playground --package @user/prompt --version 1.2.0 --input "Test input"
|
|
534
|
+
|
|
535
|
+
# Use a custom prompt string (verified authors only)
|
|
536
|
+
$ prpm playground --custom "You are a helpful coding assistant" --input "Explain async/await"
|
|
537
|
+
|
|
538
|
+
# Load custom prompt from a file (verified authors only)
|
|
539
|
+
$ prpm playground --prompt-file ./my-prompt.txt --input "Test input"
|
|
540
|
+
|
|
541
|
+
# Compare custom prompt against baseline (no prompt)
|
|
542
|
+
$ prpm playground --custom "You are concise" --input "Explain recursion" --compare
|
|
543
|
+
$ prpm playground --prompt-file ./my-prompt.txt --input "Test" --compare
|
|
544
|
+
|
|
545
|
+
# Interactive mode with custom prompt from file
|
|
546
|
+
$ prpm playground --prompt-file ./my-prompt.txt --interactive
|
|
547
|
+
|
|
548
|
+
# Short flags for common usage
|
|
549
|
+
$ prpm playground -p @user/prompt --input "Test this"
|
|
550
|
+
$ prpm playground -p @user/prompt -i
|
|
337
551
|
|
|
338
552
|
Available Models:
|
|
339
553
|
sonnet - Claude 3.5 Sonnet (default, balanced performance)
|
|
@@ -342,10 +556,16 @@ Available Models:
|
|
|
342
556
|
gpt-4o-mini - GPT-4o Mini (faster, cheaper)
|
|
343
557
|
gpt-4-turbo - GPT-4 Turbo
|
|
344
558
|
|
|
559
|
+
Custom Prompts:
|
|
560
|
+
- Available to verified authors (link your GitHub account)
|
|
561
|
+
- Cost 2x normal credits (no prompt caching)
|
|
562
|
+
- Min 10 characters, max 50,000 characters
|
|
563
|
+
- Perfect for iterating on prompt files locally
|
|
564
|
+
|
|
345
565
|
Note: Playground usage requires credits. Run 'prpm credits' to check balance.
|
|
346
566
|
`)
|
|
347
|
-
.action(async (
|
|
348
|
-
await handlePlayground(
|
|
567
|
+
.action(async (options) => {
|
|
568
|
+
await handlePlayground(options);
|
|
349
569
|
});
|
|
350
570
|
return command;
|
|
351
571
|
}
|
|
@@ -21,57 +21,41 @@ async function handleUninstall(name) {
|
|
|
21
21
|
if (!pkg) {
|
|
22
22
|
throw new errors_1.CLIError(`โ Package "${name}" not found`, 1);
|
|
23
23
|
}
|
|
24
|
-
// Get
|
|
25
|
-
const format = pkg.format || 'generic';
|
|
26
|
-
const subtype = pkg.subtype || 'rule';
|
|
24
|
+
// Get the installation path from lock file if available, otherwise calculate it
|
|
27
25
|
const packageName = (0, filesystem_1.stripAuthorNamespace)(name);
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
26
|
+
let targetPath;
|
|
27
|
+
if (pkg.installedPath) {
|
|
28
|
+
// Use the exact path where it was installed (from lock file)
|
|
29
|
+
targetPath = pkg.installedPath;
|
|
30
|
+
console.log(` ๐ Using installation path from lock file: ${targetPath}`);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
// Fallback: warn user that installedPath is missing (shouldn't happen with recent installations)
|
|
34
|
+
console.warn(` โ ๏ธ No installation path in lock file for ${name}`);
|
|
35
|
+
console.warn(` โ ๏ธ This may indicate an old or corrupted lock file`);
|
|
36
|
+
throw new errors_1.CLIError(`Cannot uninstall ${name}: installation path unknown`, 1);
|
|
37
|
+
}
|
|
38
|
+
// Check if the target path is a directory or file and delete accordingly
|
|
39
|
+
try {
|
|
40
|
+
const stats = await fs_1.promises.stat(targetPath);
|
|
41
|
+
if (stats.isDirectory()) {
|
|
42
|
+
// Delete entire directory
|
|
43
|
+
await fs_1.promises.rm(targetPath, { recursive: true, force: true });
|
|
44
|
+
console.log(` ๐๏ธ Deleted directory: ${targetPath}`);
|
|
40
45
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
console.warn(` โ ๏ธ Could not delete skill directory: ${err.message}`);
|
|
48
|
-
}
|
|
46
|
+
else if (stats.isFile()) {
|
|
47
|
+
// Delete single file
|
|
48
|
+
await fs_1.promises.unlink(targetPath);
|
|
49
|
+
console.log(` ๐๏ธ Deleted file: ${targetPath}`);
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
// Single file package
|
|
56
|
-
await (0, filesystem_1.deleteFile)(singleFilePath);
|
|
57
|
-
console.log(` ๐๏ธ Deleted file: ${singleFilePath}`);
|
|
52
|
+
catch (error) {
|
|
53
|
+
const err = error;
|
|
54
|
+
if (err.code === 'ENOENT') {
|
|
55
|
+
console.warn(` โ ๏ธ File/directory not found: ${targetPath}`);
|
|
58
56
|
}
|
|
59
57
|
else {
|
|
60
|
-
|
|
61
|
-
const packageDir = `${destDir}/${packageName}`;
|
|
62
|
-
try {
|
|
63
|
-
const stats = await fs_1.promises.stat(packageDir);
|
|
64
|
-
if (stats.isDirectory()) {
|
|
65
|
-
await fs_1.promises.rm(packageDir, { recursive: true, force: true });
|
|
66
|
-
console.log(` ๐๏ธ Deleted directory: ${packageDir}`);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
catch (error) {
|
|
70
|
-
const err = error;
|
|
71
|
-
if (err.code !== 'ENOENT') {
|
|
72
|
-
console.warn(` โ ๏ธ Could not delete package files: ${err.message}`);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
58
|
+
throw err;
|
|
75
59
|
}
|
|
76
60
|
}
|
|
77
61
|
console.log(`โ
Successfully uninstalled ${name}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prpm",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"description": "Prompt Package Manager CLI - Install and manage prompt-based files",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"license": "MIT",
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@octokit/rest": "^22.0.0",
|
|
48
|
-
"@pr-pm/registry-client": "^1.3.
|
|
49
|
-
"@pr-pm/types": "^0.2.
|
|
48
|
+
"@pr-pm/registry-client": "^1.3.11",
|
|
49
|
+
"@pr-pm/types": "^0.2.12",
|
|
50
50
|
"ajv": "^8.17.1",
|
|
51
51
|
"ajv-formats": "^3.0.1",
|
|
52
52
|
"commander": "^11.1.0",
|