replicate-predictions-downloader 1.0.0 → 2.0.1

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.
Files changed (4) hide show
  1. package/README.md +181 -11
  2. package/example.js +38 -18
  3. package/index.js +158 -4
  4. package/package.json +11 -3
package/README.md CHANGED
@@ -1,13 +1,26 @@
1
- # Replicate Predictions Downloader
1
+ # Replicate Predictions Downloader
2
2
 
3
3
  A Node.js script to download and organize all your Replicate predictions, including images, metadata, and other outputs before they expire.
4
4
 
5
- ![Replicate Downloader Banner](https://replicate.com/static/favicon.png)
5
+ ![Replicate Downloader Banner](replicate-prediction-banner.png)
6
+
7
+ <div align="center">
8
+
9
+ [![npm version](https://badge.fury.io/js/replicate-predictions-downloader.svg)](https://badge.fury.io/js/replicate-predictions-downloader)
10
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
11
+ [![Node.js](https://img.shields.io/badge/Node.js-18%2B-green.svg)](https://nodejs.org/)
12
+ [![GitHub stars](https://img.shields.io/github/stars/closestfriend/replicate-predictions-downloader.svg)](https://github.com/closestfriend/replicate-predictions-downloader/stargazers)
13
+
14
+ *A Node.js utility to preserve your Replicate AI predictions before they expire*
15
+
16
+ </div>
6
17
 
7
18
  ## Features
8
19
 
9
20
  - šŸ“„ Downloads all predictions from your Replicate account
10
21
  - šŸ—‚ļø Organizes files by model and date
22
+ - šŸ“… **NEW: Date filtering** to avoid duplicate downloads
23
+ - šŸ”„ **NEW: Incremental downloads** since last successful run
11
24
  - šŸ—œļø Creates ZIP archives for each model (optional)
12
25
  - šŸ“Š Saves enhanced metadata for all predictions
13
26
  - šŸ“ˆ Shows detailed download statistics
@@ -37,7 +50,7 @@ cd replicate-predictions-downloader
37
50
  npm install
38
51
  ```
39
52
 
40
- #### Option 2: Install via npm (coming soon)
53
+ #### Option 2: Install via npm
41
54
 
42
55
  ```bash
43
56
  npm install -g replicate-predictions-downloader
@@ -61,6 +74,8 @@ Set your API token using one of these methods:
61
74
 
62
75
  ## Usage
63
76
 
77
+ ### Basic Usage
78
+
64
79
  Run the script:
65
80
  ```bash
66
81
  # If installed locally
@@ -69,19 +84,50 @@ npm start
69
84
  # Or directly
70
85
  node index.js
71
86
 
72
- # If installed globally (coming soon)
87
+ # If installed globally
73
88
  replicate-downloader
74
89
  ```
75
90
 
76
- The script will:
77
- 1. Fetch all your predictions from Replicate
78
- 2. Download all outputs
79
- 3. Organize them by model
80
- 4. Create ZIP archives (if enabled)
81
- 5. Save detailed metadata
91
+ ### Date Filtering Options
92
+
93
+ Avoid duplicate downloads with intelligent date filtering:
94
+
95
+ ```bash
96
+ # Download predictions since a specific date
97
+ node index.js --since "2024-01-15"
98
+
99
+ # Download predictions in a date range
100
+ node index.js --since "2024-01-01" --until "2024-01-31"
101
+
102
+ # Download only new predictions since last run (recommended for regular use)
103
+ node index.js --last-run
104
+
105
+ # Download predictions from the last 7 days
106
+ node index.js --since "7 days ago"
107
+
108
+ # Download all predictions (default behavior)
109
+ node index.js --all
110
+ ```
111
+
112
+ ### Date Format Examples
113
+
114
+ The tool accepts various date formats:
115
+ - ISO dates: `"2024-01-15"`, `"2024-01-15T10:30:00Z"`
116
+ - Relative dates: `"2 days ago"`, `"1 week ago"`, `"yesterday"`
117
+ - Natural language: `"January 15, 2024"`
118
+
119
+ ### What the Script Does
120
+
121
+ 1. **Fetches predictions** from Replicate (with optional date filtering)
122
+ 2. **Downloads all outputs** for successful predictions
123
+ 3. **Organizes files** by model and date
124
+ 4. **Creates ZIP archives** for each model (if enabled)
125
+ 5. **Saves detailed metadata** and tracks state for future runs
82
126
 
83
127
  ## Configuration
84
128
 
129
+ ### Basic Settings
130
+
85
131
  You can adjust these settings in the CONFIG object:
86
132
  - `requestDelay`: Delay between API requests (ms)
87
133
  - `downloadDelay`: Delay between downloads (ms)
@@ -89,6 +135,15 @@ You can adjust these settings in the CONFIG object:
89
135
  - `createZips`: Whether to create ZIP archives
90
136
  - `enhancedMetadata`: Whether to save enhanced metadata
91
137
 
138
+ ### State Tracking
139
+
140
+ The tool automatically creates a `.replicate-downloader-state.json` file to track:
141
+ - Last successful run timestamp
142
+ - Total predictions processed
143
+ - Successful predictions count
144
+
145
+ This enables the `--last-run` option for incremental downloads without duplicates.
146
+
92
147
  ## Output Structure
93
148
 
94
149
  The tool creates a directory structure like this:
@@ -113,6 +168,27 @@ replicate_metadata_YYYY-MM-DD.json
113
168
 
114
169
  This is a tool I created for personal use. I'm sharing it in case others find it helpful, but I may not be able to provide extensive support. Pull requests are welcome!
115
170
 
171
+ ## Command-Line Interface
172
+
173
+ The tool now includes a comprehensive CLI with help and version information:
174
+
175
+ ```bash
176
+ # Show help
177
+ node index.js --help
178
+
179
+ # Show version
180
+ node index.js --version
181
+
182
+ # Available options
183
+ Options:
184
+ -s, --since <date> Download predictions created since this date
185
+ -u, --until <date> Download predictions created until this date
186
+ -l, --last-run Download only predictions since last successful run
187
+ --all Download all predictions (default behavior)
188
+ -h, --help Display help for command
189
+ -V, --version Display version for command
190
+ ```
191
+
116
192
  ## Contributing
117
193
 
118
194
  Contributions are welcome! Please feel free to submit a Pull Request.
@@ -128,4 +204,98 @@ This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md
128
204
 
129
205
  ## Background
130
206
 
131
- This tool was created while working on LLM behavior/personality research to preserve valuable predictions before they expired.
207
+ Replicate is a powerful platform for running AI models, but predictions don't last forever - they expire after a period of time. This tool was originally created while working on LLM behavior/personality research when I realized I was losing valuable generated content.
208
+
209
+ After generating hundreds of images with Stable Diffusion, video clips, and other AI outputs, I needed a way to systematically download and organize everything before it disappeared. The tool has since evolved into a comprehensive solution for anyone who wants to preserve their Replicate predictions with intelligent organization and duplicate prevention.
210
+
211
+ ## Quick Start
212
+
213
+ Get up and running in 2 minutes:
214
+
215
+ 1. **Get your API token**: Visit [replicate.com/account/api-tokens](https://replicate.com/account/api-tokens)
216
+
217
+ 2. **Set your token**:
218
+ ```bash
219
+ export REPLICATE_API_TOKEN=your_token_here
220
+ ```
221
+
222
+ 3. **Install and run**:
223
+ ```bash
224
+ # Clone and install
225
+ git clone https://github.com/closestfriend/replicate-predictions-downloader.git
226
+ cd replicate-predictions-downloader
227
+ npm install
228
+
229
+ # Download all your predictions
230
+ npm start
231
+
232
+ # Or just new ones since last run (recommended for regular use)
233
+ node index.js --last-run
234
+ ```
235
+
236
+ That's it! Your predictions will be downloaded and organized by model and date.
237
+
238
+ ## What You'll See
239
+
240
+ When you run the downloader, here's what happens:
241
+
242
+ ```
243
+ Starting Replicate Predictions Downloader v2.0.0
244
+ Using date filter: since 2024-01-01
245
+ Fetching predictions from Replicate API...
246
+ Found 47 predictions to process
247
+
248
+ PROCESSING STATISTICS:
249
+ ā”œā”€ā”€ Total predictions: 47
250
+ ā”œā”€ā”€ Successful: 43 (91.5%)
251
+ ā”œā”€ā”€ Failed: 4 (8.5%)
252
+ └── Models found: 8
253
+
254
+ DOWNLOADING OUTPUTS:
255
+ ā”œā”€ā”€ stable-diffusion-xl: 25 images
256
+ ā”œā”€ā”€ midjourney-v6: 12 images
257
+ ā”œā”€ā”€ whisper-large-v3: 8 audio files
258
+ └── llama-2-70b-chat: 6 text files
259
+
260
+ SAVING TO: replicate_outputs_2024-01-15/
261
+ ā”œā”€ā”€ by-model/
262
+ │ ā”œā”€ā”€ stable-diffusion-xl/
263
+ │ ā”œā”€ā”€ midjourney-v6/
264
+ │ └── ...
265
+ ā”œā”€ā”€ stable-diffusion-xl.zip
266
+ ā”œā”€ā”€ midjourney-v6.zip
267
+ └── replicate_metadata_2024-01-15.json
268
+
269
+ Complete! Downloaded 51 files (127.3 MB)
270
+ Elapsed time: 2m 34s
271
+ Next time, use --last-run to download only new predictions
272
+ ```
273
+
274
+ ## Common Issues
275
+
276
+ **"Invalid API token" or "Authentication failed"**
277
+ - Double-check your token at [replicate.com/account/api-tokens](https://replicate.com/account/api-tokens)
278
+ - Make sure you've set `REPLICATE_API_TOKEN` in your environment or `.env` file
279
+ - Try: `echo $REPLICATE_API_TOKEN` to verify it's set
280
+
281
+ **"Network timeout" or connection errors**
282
+ - Check your internet connection
283
+ - The tool automatically retries failed downloads
284
+ - For persistent issues, try running with fewer concurrent requests by editing the CONFIG object
285
+
286
+ **"Permission denied" or file errors**
287
+ - Ensure you have write permissions in the current directory
288
+ - On Windows, try running as administrator if needed
289
+ - Make sure you have enough disk space for your downloads
290
+
291
+ **"No new predictions found"**
292
+ - If using `--last-run`, this means you're up to date!
293
+ - Try `--since "1 week ago"` to see recent predictions
294
+ - Use `--all` to redownload everything (may create duplicates)
295
+
296
+ **Files have weird names or special characters**
297
+ - The tool automatically sanitizes filenames
298
+ - Prompts longer than the limit (default: 50 chars) are truncated
299
+ - Adjust `maxPromptLength` in CONFIG if needed
300
+
301
+ **Need help?** Check existing [GitHub issues](https://github.com/closestfriend/replicate-predictions-downloader/issues) or create a new one.
package/example.js CHANGED
@@ -1,4 +1,4 @@
1
- // Example of using ReplicateDownloader as a module
1
+ // Example of using ReplicateDownloader as a module with date filtering
2
2
  import ReplicateDownloader from './index.js';
3
3
  import dotenv from 'dotenv';
4
4
 
@@ -15,25 +15,45 @@ async function example() {
15
15
 
16
16
  console.log('Starting Replicate Downloader example...');
17
17
 
18
- // Create a new instance with your API token
19
- const downloader = new ReplicateDownloader(process.env.REPLICATE_API_TOKEN);
18
+ // Example 1: Download all predictions (default behavior)
19
+ console.log('\nšŸ“„ Example 1: Download all predictions');
20
+ const downloader1 = new ReplicateDownloader(process.env.REPLICATE_API_TOKEN);
21
+ // await downloader1.run(); // Uncomment to run
20
22
 
21
- // Optional: Override default configuration
22
- // downloader.config = {
23
- // requestDelay: 500, // Increase delay between API requests
24
- // downloadDelay: 200, // Increase delay between downloads
25
- // maxPromptLength: 30, // Shorter prompt in filenames
26
- // createZips: false, // Disable ZIP creation
27
- // enhancedMetadata: true // Keep enhanced metadata
28
- // };
23
+ // Example 2: Download predictions since a specific date
24
+ console.log('\nšŸ“… Example 2: Download predictions since 2024-01-01');
25
+ const downloader2 = new ReplicateDownloader(process.env.REPLICATE_API_TOKEN, {
26
+ since: '2024-01-01'
27
+ });
28
+ // await downloader2.run(); // Uncomment to run
29
29
 
30
- try {
31
- // Run the downloader
32
- await downloader.run();
33
- console.log('Example completed successfully!');
34
- } catch (error) {
35
- console.error('Example failed:', error.message);
36
- }
30
+ // Example 3: Download predictions in a date range
31
+ console.log('\nšŸ“… Example 3: Download predictions between 2024-01-01 and 2024-01-31');
32
+ const downloader3 = new ReplicateDownloader(process.env.REPLICATE_API_TOKEN, {
33
+ since: '2024-01-01',
34
+ until: '2024-01-31'
35
+ });
36
+ // await downloader3.run(); // Uncomment to run
37
+
38
+ // Example 4: Incremental download (since last run)
39
+ console.log('\nšŸ”„ Example 4: Incremental download since last successful run');
40
+ const downloader4 = new ReplicateDownloader(process.env.REPLICATE_API_TOKEN, {
41
+ lastRun: true
42
+ });
43
+ // await downloader4.run(); // Uncomment to run
44
+
45
+ // Example 5: Download predictions from the last 7 days
46
+ console.log('\nšŸ“… Example 5: Download predictions from the last 7 days');
47
+ const sevenDaysAgo = new Date();
48
+ sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);
49
+ const downloader5 = new ReplicateDownloader(process.env.REPLICATE_API_TOKEN, {
50
+ since: sevenDaysAgo.toISOString()
51
+ });
52
+ // await downloader5.run(); // Uncomment to run
53
+
54
+ console.log('\nšŸ’” To run any example, uncomment the corresponding await line');
55
+ console.log('šŸ’” The tool automatically saves state for incremental downloads');
56
+ console.log('šŸ’” Use --help for command-line options when running directly');
37
57
  }
38
58
 
39
59
  // Run the example
package/index.js CHANGED
@@ -2,6 +2,11 @@ import fs from 'fs';
2
2
  import path from 'path';
3
3
  import https from 'https';
4
4
  import archiver from 'archiver';
5
+ import { Command } from 'commander';
6
+ import dotenv from 'dotenv';
7
+
8
+ // Load environment variables
9
+ dotenv.config();
5
10
 
6
11
  // Get API token from environment variable
7
12
  const REPLICATE_API_TOKEN = process.env.REPLICATE_API_TOKEN;
@@ -16,7 +21,7 @@ const CONFIG = {
16
21
  };
17
22
 
18
23
  class ReplicateDownloader {
19
- constructor(apiToken) {
24
+ constructor(apiToken, options = {}) {
20
25
  this.apiToken = apiToken;
21
26
  this.baseUrl = 'https://api.replicate.com/v1';
22
27
  this.allPredictions = [];
@@ -25,6 +30,82 @@ class ReplicateDownloader {
25
30
  totalFiles: 0,
26
31
  totalSize: 0
27
32
  };
33
+
34
+ // Date filtering options
35
+ this.dateFilters = {
36
+ since: options.since || null,
37
+ until: options.until || null,
38
+ lastRun: options.lastRun || false
39
+ };
40
+
41
+ this.stateFile = '.replicate-downloader-state.json';
42
+ }
43
+
44
+ // Load state from previous runs
45
+ loadState() {
46
+ try {
47
+ if (fs.existsSync(this.stateFile)) {
48
+ const state = JSON.parse(fs.readFileSync(this.stateFile, 'utf8'));
49
+ return state;
50
+ }
51
+ } catch (error) {
52
+ console.warn('Warning: Could not load state file:', error.message);
53
+ }
54
+ return { lastSuccessfulRun: null };
55
+ }
56
+
57
+ // Save state for future runs
58
+ saveState(state) {
59
+ try {
60
+ fs.writeFileSync(this.stateFile, JSON.stringify(state, null, 2));
61
+ } catch (error) {
62
+ console.warn('Warning: Could not save state file:', error.message);
63
+ }
64
+ }
65
+
66
+ // Parse date string to ISO format
67
+ parseDate(dateStr) {
68
+ if (!dateStr) return null;
69
+
70
+ // Handle various date formats
71
+ const date = new Date(dateStr);
72
+ if (isNaN(date.getTime())) {
73
+ throw new Error(`Invalid date format: ${dateStr}. Use formats like "2024-01-15", "2024-01-15T10:30:00Z", or "2 days ago"`);
74
+ }
75
+
76
+ return date.toISOString();
77
+ }
78
+
79
+ // Get date filter parameters for API
80
+ getDateFilterParams() {
81
+ const params = new URLSearchParams();
82
+
83
+ let sinceDate = this.dateFilters.since;
84
+
85
+ // Handle --last-run option
86
+ if (this.dateFilters.lastRun) {
87
+ const state = this.loadState();
88
+ if (state.lastSuccessfulRun) {
89
+ sinceDate = state.lastSuccessfulRun;
90
+ console.log(`Using last run date: ${sinceDate}`);
91
+ } else {
92
+ console.log('No previous run found, downloading all predictions');
93
+ }
94
+ }
95
+
96
+ if (sinceDate) {
97
+ const parsedSince = this.parseDate(sinceDate);
98
+ // Add a small buffer to avoid edge cases
99
+ const sinceBuffer = new Date(new Date(parsedSince).getTime() - 1000);
100
+ params.append('created_at.gte', sinceBuffer.toISOString());
101
+ }
102
+
103
+ if (this.dateFilters.until) {
104
+ const parsedUntil = this.parseDate(this.dateFilters.until);
105
+ params.append('created_at.lte', parsedUntil);
106
+ }
107
+
108
+ return params.toString();
28
109
  }
29
110
 
30
111
  // Make authenticated request to Replicate API
@@ -133,11 +214,18 @@ class ReplicateDownloader {
133
214
  });
134
215
  }
135
216
 
136
- // Fetch all predictions with pagination
217
+ // Fetch all predictions with pagination and date filtering
137
218
  async fetchAllPredictions() {
138
219
  let nextUrl = `${this.baseUrl}/predictions`;
139
220
  let page = 1;
140
221
 
222
+ // Apply date filtering
223
+ const dateParams = this.getDateFilterParams();
224
+ if (dateParams) {
225
+ nextUrl += `?${dateParams}`;
226
+ console.log('Applying date filters:', dateParams);
227
+ }
228
+
141
229
  console.log('Starting to fetch predictions...');
142
230
 
143
231
  while (nextUrl) {
@@ -152,7 +240,19 @@ class ReplicateDownloader {
152
240
  console.log(`Total so far: ${this.allPredictions.length}`);
153
241
  }
154
242
 
155
- nextUrl = response.next;
243
+ // Handle pagination with date filters
244
+ if (response.next) {
245
+ // Ensure date filters are preserved in next URL
246
+ if (dateParams && !response.next.includes('created_at')) {
247
+ const separator = response.next.includes('?') ? '&' : '?';
248
+ nextUrl = `${response.next}${separator}${dateParams}`;
249
+ } else {
250
+ nextUrl = response.next;
251
+ }
252
+ } else {
253
+ nextUrl = null;
254
+ }
255
+
156
256
  page++;
157
257
 
158
258
  // Custom delay
@@ -399,12 +499,38 @@ class ReplicateDownloader {
399
499
  console.log(` āŒ Failed: ${failed}`);
400
500
  console.log(` ā¹ļø Canceled: ${canceled}`);
401
501
 
502
+ // Save state for future runs
503
+ if (successful > 0) {
504
+ const state = {
505
+ lastSuccessfulRun: new Date().toISOString(),
506
+ totalPredictions: this.allPredictions.length,
507
+ successfulPredictions: successful
508
+ };
509
+ this.saveState(state);
510
+ console.log('\nšŸ’¾ State saved for future incremental downloads');
511
+ }
512
+
402
513
  } catch (error) {
403
514
  console.error('šŸ’„ Fatal error:', error.message);
404
515
  }
405
516
  }
406
517
  }
407
518
 
519
+ // Setup command-line interface
520
+ const program = new Command();
521
+
522
+ program
523
+ .name('replicate-downloader')
524
+ .description('Download and organize Replicate predictions with date filtering')
525
+ .version('2.0.0')
526
+ .option('-s, --since <date>', 'Download predictions created since this date (ISO format, e.g., "2024-01-15" or "2 days ago")')
527
+ .option('-u, --until <date>', 'Download predictions created until this date (ISO format)')
528
+ .option('-l, --last-run', 'Download only predictions created since the last successful run')
529
+ .option('--all', 'Download all predictions (default behavior)')
530
+ .parse();
531
+
532
+ const options = program.opts();
533
+
408
534
  // Usage
409
535
  async function main() {
410
536
  if (!REPLICATE_API_TOKEN) {
@@ -418,7 +544,35 @@ async function main() {
418
544
  return;
419
545
  }
420
546
 
421
- const downloader = new ReplicateDownloader(REPLICATE_API_TOKEN);
547
+ // Validate date options
548
+ if (options.since && options.lastRun) {
549
+ console.error('āŒ Cannot use both --since and --last-run options together');
550
+ return;
551
+ }
552
+
553
+ if (options.until && options.lastRun) {
554
+ console.error('āŒ Cannot use both --until and --last-run options together');
555
+ return;
556
+ }
557
+
558
+ const downloaderOptions = {};
559
+
560
+ if (options.since) {
561
+ downloaderOptions.since = options.since;
562
+ console.log(`šŸ“… Filtering predictions since: ${options.since}`);
563
+ }
564
+
565
+ if (options.until) {
566
+ downloaderOptions.until = options.until;
567
+ console.log(`šŸ“… Filtering predictions until: ${options.until}`);
568
+ }
569
+
570
+ if (options.lastRun) {
571
+ downloaderOptions.lastRun = true;
572
+ console.log('šŸ”„ Using incremental download (since last run)');
573
+ }
574
+
575
+ const downloader = new ReplicateDownloader(REPLICATE_API_TOKEN, downloaderOptions);
422
576
  await downloader.run();
423
577
  }
424
578
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicate-predictions-downloader",
3
- "version": "1.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "A Node.js script to download and organize all your Replicate predictions, including images, metadata, and other outputs",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -17,7 +17,14 @@
17
17
  "predictions",
18
18
  "organization",
19
19
  "replicate-api",
20
- "model-outputs"
20
+ "model-outputs",
21
+ "stable-diffusion",
22
+ "midjourney-alternative",
23
+ "ai-art",
24
+ "batch-download",
25
+ "backup",
26
+ "archive",
27
+ "cli"
21
28
  ],
22
29
  "author": "closestfriend",
23
30
  "license": "MIT",
@@ -34,7 +41,8 @@
34
41
  },
35
42
  "dependencies": {
36
43
  "archiver": "^5.3.1",
37
- "dotenv": "^16.3.1"
44
+ "dotenv": "^16.3.1",
45
+ "commander": "^11.0.0"
38
46
  },
39
47
  "files": [
40
48
  "index.js",