prpm 0.1.4 → 0.1.6

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.
@@ -0,0 +1,351 @@
1
+ "use strict";
2
+ /**
3
+ * Playground command - Test packages with AI models
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.handlePlayground = handlePlayground;
40
+ exports.createPlaygroundCommand = createPlaygroundCommand;
41
+ const commander_1 = require("commander");
42
+ const user_config_1 = require("../core/user-config");
43
+ const telemetry_1 = require("../core/telemetry");
44
+ const readline = __importStar(require("readline"));
45
+ /**
46
+ * Create a readline interface for user input
47
+ */
48
+ function createReadline() {
49
+ return readline.createInterface({
50
+ input: process.stdin,
51
+ output: process.stdout,
52
+ });
53
+ }
54
+ /**
55
+ * Prompt user for input
56
+ */
57
+ function prompt(rl, question) {
58
+ return new Promise((resolve) => {
59
+ rl.question(question, (answer) => {
60
+ resolve(answer);
61
+ });
62
+ });
63
+ }
64
+ /**
65
+ * Make authenticated API call to registry
66
+ */
67
+ async function apiCall(endpoint, method = 'GET', body) {
68
+ const config = await (0, user_config_1.getConfig)();
69
+ const baseUrl = (config.registryUrl || "https://registry.prpm.dev").replace(/\/$/, '');
70
+ if (!config.token) {
71
+ throw new Error('Authentication required. Please run `prpm login` first.');
72
+ }
73
+ const response = await fetch(`${baseUrl}${endpoint}`, {
74
+ method,
75
+ headers: {
76
+ 'Content-Type': 'application/json',
77
+ Authorization: `Bearer ${config.token}`,
78
+ },
79
+ body: body ? JSON.stringify(body) : undefined,
80
+ });
81
+ if (!response.ok) {
82
+ const errorData = await response.json().catch(() => ({}));
83
+ throw new Error(errorData.message || `API request failed: ${response.statusText}`);
84
+ }
85
+ return response;
86
+ }
87
+ /**
88
+ * Resolve package name to UUID
89
+ */
90
+ async function resolvePackageId(packageName) {
91
+ // If it's already a UUID, return it
92
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
93
+ if (uuidRegex.test(packageName)) {
94
+ return packageName;
95
+ }
96
+ // Search for the package by name
97
+ const config = await (0, user_config_1.getConfig)();
98
+ const baseUrl = (config.registryUrl || "https://registry.prpm.dev").replace(/\/$/, '');
99
+ const response = await fetch(`${baseUrl}/api/v1/search?q=${encodeURIComponent(packageName)}&limit=10`);
100
+ if (!response.ok) {
101
+ throw new Error(`Failed to search for package: ${response.statusText}`);
102
+ }
103
+ const data = await response.json();
104
+ // Find exact match
105
+ const exactMatch = data.packages.find(pkg => pkg.name === packageName);
106
+ if (exactMatch) {
107
+ return exactMatch.id;
108
+ }
109
+ // If no exact match, throw error
110
+ throw new Error(`Package not found: ${packageName}`);
111
+ }
112
+ /**
113
+ * Execute a playground run
114
+ */
115
+ async function runPlayground(packageName, input, options, sessionId) {
116
+ // Resolve package name to UUID
117
+ const packageId = await resolvePackageId(packageName);
118
+ const response = await apiCall('/api/v1/playground/run', 'POST', {
119
+ package_id: packageId,
120
+ package_version: options.version,
121
+ input,
122
+ model: options.model || 'sonnet',
123
+ use_no_prompt: options.compare || false,
124
+ session_id: sessionId,
125
+ });
126
+ return response.json();
127
+ }
128
+ /**
129
+ * Format and display playground response
130
+ */
131
+ function displayResponse(result, showStats = true) {
132
+ // Get the latest assistant response
133
+ const lastMessage = result.conversation[result.conversation.length - 1];
134
+ if (lastMessage?.role === 'assistant') {
135
+ console.log('\n' + '─'.repeat(60));
136
+ console.log('šŸ¤– Assistant:');
137
+ console.log('─'.repeat(60));
138
+ console.log(lastMessage.content);
139
+ console.log('─'.repeat(60));
140
+ }
141
+ if (showStats) {
142
+ console.log(`\nšŸ“Š Stats:`);
143
+ console.log(` Model: ${result.model}`);
144
+ console.log(` Tokens: ${result.tokens_used.toLocaleString()}`);
145
+ console.log(` Credits spent: ${result.credits_spent}`);
146
+ console.log(` Credits remaining: ${result.credits_remaining}`);
147
+ console.log(` Duration: ${result.duration_ms}ms`);
148
+ }
149
+ }
150
+ /**
151
+ * Run interactive playground session
152
+ */
153
+ async function runInteractive(packageName, options) {
154
+ console.log('\nšŸŽ® Interactive Playground Mode');
155
+ console.log(` Package: ${packageName}`);
156
+ console.log(` Model: ${options.model || 'sonnet'}`);
157
+ if (options.compare) {
158
+ console.log(` Mode: Comparing against no prompt (raw model baseline)`);
159
+ }
160
+ console.log(` Type 'exit' or 'quit' to end session\n`);
161
+ const rl = createReadline();
162
+ let sessionId;
163
+ let turnCount = 0;
164
+ try {
165
+ while (true) {
166
+ const input = await prompt(rl, `\nšŸ’¬ You: `);
167
+ if (input.trim().toLowerCase() === 'exit' || input.trim().toLowerCase() === 'quit') {
168
+ console.log('\nšŸ‘‹ Ending playground session. Goodbye!');
169
+ break;
170
+ }
171
+ if (!input.trim()) {
172
+ console.log('āŒ Please enter a message');
173
+ continue;
174
+ }
175
+ try {
176
+ console.log('\nā³ Processing...');
177
+ const result = await runPlayground(packageName, input, options, sessionId);
178
+ // Store session ID for conversation continuity
179
+ sessionId = result.session_id;
180
+ turnCount++;
181
+ displayResponse(result, true);
182
+ }
183
+ catch (error) {
184
+ console.error(`\nāŒ Error: ${error instanceof Error ? error.message : String(error)}`);
185
+ if (error instanceof Error && error.message.includes('Insufficient credits')) {
186
+ console.log('\nšŸ’” Get more credits:');
187
+ console.log(' - Purchase credits: prpm buy-credits');
188
+ console.log(' - Subscribe to PRPM+: prpm subscribe');
189
+ console.log(' - Check balance: prpm credits');
190
+ break;
191
+ }
192
+ }
193
+ }
194
+ if (turnCount > 0) {
195
+ console.log(`\nšŸ“ Session summary: ${turnCount} turn(s)`);
196
+ }
197
+ }
198
+ finally {
199
+ rl.close();
200
+ }
201
+ }
202
+ /**
203
+ * Run single playground query
204
+ */
205
+ async function runSingle(packageName, input, options) {
206
+ console.log(`\nšŸŽ® Testing package: ${packageName}`);
207
+ console.log(` Model: ${options.model || 'sonnet'}`);
208
+ if (options.compare) {
209
+ console.log(` Mode: Comparing with package vs. without (baseline)`);
210
+ }
211
+ try {
212
+ if (options.compare) {
213
+ // Comparison mode: run both with package and without
214
+ console.log('\nā³ Processing comparison (2 requests)...');
215
+ // Run with package (without use_no_prompt flag)
216
+ const withPackageOptions = { ...options, compare: false };
217
+ const resultWithPackage = await runPlayground(packageName, input, withPackageOptions);
218
+ // Run without package (with use_no_prompt flag)
219
+ const withoutPackageOptions = { ...options, compare: true };
220
+ const resultWithoutPackage = await runPlayground(packageName, input, withoutPackageOptions);
221
+ // Display both results
222
+ console.log('\n' + '═'.repeat(60));
223
+ console.log('šŸ“¦ WITH PACKAGE PROMPT');
224
+ console.log('═'.repeat(60));
225
+ displayResponse(resultWithPackage, false);
226
+ console.log('\n' + '═'.repeat(60));
227
+ console.log('šŸ”µ WITHOUT PACKAGE (BASELINE)');
228
+ console.log('═'.repeat(60));
229
+ displayResponse(resultWithoutPackage, false);
230
+ // Combined stats
231
+ console.log(`\nšŸ“Š Combined Stats:`);
232
+ console.log(` Total tokens: ${resultWithPackage.tokens_used + resultWithoutPackage.tokens_used}`);
233
+ console.log(` Total credits: ${resultWithPackage.credits_spent + resultWithoutPackage.credits_spent}`);
234
+ console.log(` Credits remaining: ${resultWithoutPackage.credits_remaining}`);
235
+ }
236
+ else {
237
+ // Single mode: run with package only
238
+ console.log('\nā³ Processing...');
239
+ const result = await runPlayground(packageName, input, options);
240
+ displayResponse(result, true);
241
+ }
242
+ console.log(`\nšŸ’” Tips:`);
243
+ console.log(` - Use --interactive for multi-turn conversation`);
244
+ console.log(` - Use --compare to test with and without the package prompt`);
245
+ console.log(` - Use --model to choose different models (sonnet, opus, gpt-4o, etc.)`);
246
+ }
247
+ catch (error) {
248
+ console.error(`\nāŒ Error: ${error instanceof Error ? error.message : String(error)}`);
249
+ if (error instanceof Error && error.message.includes('Insufficient credits')) {
250
+ console.log('\nšŸ’” Get more credits:');
251
+ console.log(' - Purchase credits: prpm buy-credits');
252
+ console.log(' - Subscribe to PRPM+: prpm subscribe');
253
+ console.log(' - Check balance: prpm credits');
254
+ }
255
+ process.exit(1);
256
+ }
257
+ }
258
+ /**
259
+ * Handle the playground command
260
+ */
261
+ async function handlePlayground(packageName, input, options) {
262
+ const startTime = Date.now();
263
+ let success = false;
264
+ let error;
265
+ try {
266
+ // Validate authentication
267
+ const config = await (0, user_config_1.getConfig)();
268
+ if (!config.token) {
269
+ console.error('āŒ Authentication required');
270
+ console.log('\nšŸ’” Please login first:');
271
+ console.log(' prpm login');
272
+ process.exit(1);
273
+ }
274
+ // Interactive mode or single query
275
+ if (options.interactive || !input) {
276
+ // Interactive mode
277
+ await runInteractive(packageName, options);
278
+ }
279
+ else {
280
+ // Single query mode
281
+ await runSingle(packageName, input, options);
282
+ }
283
+ success = true;
284
+ }
285
+ catch (err) {
286
+ error = err instanceof Error ? err.message : String(err);
287
+ console.error(`\nāŒ Playground execution failed: ${error}`);
288
+ process.exit(1);
289
+ }
290
+ finally {
291
+ await telemetry_1.telemetry.track({
292
+ command: 'playground',
293
+ success,
294
+ error,
295
+ duration: Date.now() - startTime,
296
+ data: {
297
+ packageName,
298
+ model: options.model || 'sonnet',
299
+ compare: options.compare || false,
300
+ interactive: options.interactive || false,
301
+ },
302
+ });
303
+ await telemetry_1.telemetry.shutdown();
304
+ }
305
+ }
306
+ /**
307
+ * Create the playground command
308
+ */
309
+ function createPlaygroundCommand() {
310
+ const command = new commander_1.Command('playground');
311
+ command
312
+ .description('Test a package with AI models in the playground')
313
+ .argument('<package>', 'Package name to test')
314
+ .argument('[input]', 'Input text to send to the model (omit for interactive mode)')
315
+ .option('-m, --model <model>', 'AI model to use (sonnet, opus, gpt-4o, gpt-4o-mini, gpt-4-turbo)', 'sonnet')
316
+ .option('-c, --compare', 'Compare against no prompt (test raw model baseline)', false)
317
+ .option('-i, --interactive', 'Start interactive multi-turn conversation mode', false)
318
+ .option('-v, --version <version>', 'Specific package version to test')
319
+ .addHelpText('after', `
320
+ Examples:
321
+ # Single query with default model (Sonnet)
322
+ $ prpm playground @anthropic/code-reviewer "Review this code: console.log('hello')"
323
+
324
+ # Interactive mode for multi-turn conversation
325
+ $ prpm playground @anthropic/brainstorm-assistant --interactive
326
+
327
+ # Compare with and without the package prompt
328
+ $ prpm playground @user/custom-prompt "Test input" --compare
329
+
330
+ # Use a different model
331
+ $ prpm playground @user/prompt --model opus "Complex task requiring Opus"
332
+ $ prpm playground @user/prompt --model gpt-4o "Test with GPT-4o"
333
+
334
+ # Test specific version
335
+ $ prpm playground @user/prompt@1.2.0 "Test input"
336
+
337
+ Available Models:
338
+ sonnet - Claude 3.5 Sonnet (default, balanced performance)
339
+ opus - Claude 3 Opus (most capable, higher cost)
340
+ gpt-4o - GPT-4o (OpenAI's latest)
341
+ gpt-4o-mini - GPT-4o Mini (faster, cheaper)
342
+ gpt-4-turbo - GPT-4 Turbo
343
+
344
+ Note: Playground usage requires credits. Run 'prpm credits' to check balance.
345
+ `)
346
+ .action(async (packageName, input, options) => {
347
+ await handlePlayground(packageName, input, options);
348
+ process.exit(0);
349
+ });
350
+ return command;
351
+ }
@@ -90,6 +90,7 @@ async function findAndLoadManifests() {
90
90
  homepage: pkg.homepage ?? multiManifest.homepage,
91
91
  documentation: pkg.documentation ?? multiManifest.documentation,
92
92
  organization: pkg.organization ?? multiManifest.organization,
93
+ private: pkg.private ?? multiManifest.private,
93
94
  tags: pkg.tags ?? multiManifest.tags,
94
95
  keywords: pkg.keywords ?? multiManifest.keywords,
95
96
  subtype: pkg.subtype,
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ /**
3
+ * Remove command implementation
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.handleRemove = handleRemove;
7
+ exports.createRemoveCommand = createRemoveCommand;
8
+ const commander_1 = require("commander");
9
+ const lockfile_1 = require("../core/lockfile");
10
+ const filesystem_1 = require("../core/filesystem");
11
+ const fs_1 = require("fs");
12
+ /**
13
+ * Handle the remove command
14
+ */
15
+ async function handleRemove(name) {
16
+ try {
17
+ console.log(`šŸ—‘ļø Removing package: ${name}`);
18
+ // Remove from lockfile and get package info
19
+ const pkg = await (0, lockfile_1.removePackage)(name);
20
+ if (!pkg) {
21
+ console.error(`āŒ Package "${name}" not found`);
22
+ process.exit(1);
23
+ }
24
+ // Determine file path based on package type and format
25
+ const effectiveType = (pkg.format === 'claude' ? 'claude-skill' :
26
+ pkg.format === 'cursor' ? 'cursor' :
27
+ pkg.format === 'continue' ? 'continue' :
28
+ pkg.format === 'windsurf' ? 'windsurf' :
29
+ pkg.type);
30
+ const destDir = (0, filesystem_1.getDestinationDir)(effectiveType);
31
+ const fileExtension = pkg.format === 'cursor' ? 'mdc' : 'md';
32
+ // Strip author namespace to get just the package name
33
+ const packageName = (0, filesystem_1.stripAuthorNamespace)(name);
34
+ // Try single file first
35
+ const singleFilePath = `${destDir}/${packageName}.${fileExtension}`;
36
+ if (await (0, filesystem_1.fileExists)(singleFilePath)) {
37
+ // Single file package
38
+ await (0, filesystem_1.deleteFile)(singleFilePath);
39
+ console.log(` šŸ—‘ļø Deleted file: ${singleFilePath}`);
40
+ }
41
+ else {
42
+ // Try multi-file package directory
43
+ const packageDir = `${destDir}/${packageName}`;
44
+ try {
45
+ const stats = await fs_1.promises.stat(packageDir);
46
+ if (stats.isDirectory()) {
47
+ await fs_1.promises.rm(packageDir, { recursive: true, force: true });
48
+ console.log(` šŸ—‘ļø Deleted directory: ${packageDir}`);
49
+ }
50
+ }
51
+ catch (error) {
52
+ const err = error;
53
+ if (err.code !== 'ENOENT') {
54
+ console.warn(` āš ļø Could not delete package files: ${err.message}`);
55
+ }
56
+ }
57
+ }
58
+ console.log(`āœ… Successfully removed ${name}`);
59
+ process.exit(0);
60
+ }
61
+ catch (error) {
62
+ console.error(`āŒ Failed to remove package: ${error}`);
63
+ process.exit(1);
64
+ }
65
+ }
66
+ /**
67
+ * Create the remove command
68
+ */
69
+ function createRemoveCommand() {
70
+ const command = new commander_1.Command('remove');
71
+ command
72
+ .description('Remove a prompt package')
73
+ .argument('<id>', 'Package ID to remove')
74
+ .action(handleRemove);
75
+ return command;
76
+ }
@@ -134,6 +134,10 @@ function buildWebappUrl(query, options, page = 1) {
134
134
  params.append('subtype', options.subtype);
135
135
  if (options.author)
136
136
  params.append('author', options.author);
137
+ if (options.language)
138
+ params.append('language', options.language);
139
+ if (options.framework)
140
+ params.append('framework', options.framework);
137
141
  if (page > 1)
138
142
  params.append('page', page.toString());
139
143
  return `${baseUrl}/search?${params.toString()}`;
@@ -312,6 +316,12 @@ async function handleSearch(query, options) {
312
316
  if (options.author) {
313
317
  searchOptions.author = options.author;
314
318
  }
319
+ if (options.language) {
320
+ searchOptions.language = options.language;
321
+ }
322
+ if (options.framework) {
323
+ searchOptions.framework = options.framework;
324
+ }
315
325
  result = await client.search(query || '', searchOptions);
316
326
  if (!result || result.packages.length === 0) {
317
327
  console.log('\nāŒ No packages found');
@@ -377,6 +387,8 @@ async function handleSearch(query, options) {
377
387
  query: query.substring(0, 100),
378
388
  format: options.format,
379
389
  subtype: options.subtype,
390
+ language: options.language,
391
+ framework: options.framework,
380
392
  resultCount: success && result ? result.packages.length : 0,
381
393
  page: options.page,
382
394
  interactive: options.interactive,
@@ -394,6 +406,8 @@ function createSearchCommand() {
394
406
  .option('--format <format>', 'Filter by package format (cursor, claude, continue, windsurf, copilot, kiro, agents.md, generic, mcp)')
395
407
  .option('--subtype <subtype>', 'Filter by package subtype (rule, agent, skill, slash-command, prompt, workflow, tool, template, collection)')
396
408
  .option('--author <username>', 'Filter by author username')
409
+ .option('--language <language>', 'Filter by programming language (javascript, typescript, python, etc.)')
410
+ .option('--framework <framework>', 'Filter by framework (react, nextjs, django, etc.)')
397
411
  .option('--limit <number>', 'Number of results per page', '20')
398
412
  .option('--page <number>', 'Page number (default: 1)', '1')
399
413
  .option('--interactive', 'Enable interactive pagination (default: true for multiple pages)', true)
@@ -423,7 +437,7 @@ function createSearchCommand() {
423
437
  console.log(` prpm search --author prpm # List packages by @prpm`);
424
438
  process.exit(1);
425
439
  }
426
- await handleSearch(query || '', { format, subtype, author, limit, page, interactive: options.interactive });
440
+ await handleSearch(query || '', { format, subtype, author, language: options.language, framework: options.framework, limit, page, interactive: options.interactive });
427
441
  process.exit(0);
428
442
  });
429
443
  return command;