promptcase 1.0.6 → 1.0.8

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.
@@ -287,7 +287,22 @@ export class ClaudeCaptureService {
287
287
  }
288
288
  /**
289
289
  * Get all prompts from all sources (project transcripts + history),
290
- * deduplicated by SHA-256 content hash, sorted newest first.
290
+ * deduplicated by SHA-256 content hash.
291
+ *
292
+ * Two modes:
293
+ *
294
+ * 1. **Initial backfill** (no `since` cursor): fetch the **latest** N
295
+ * prompts and sort them **newest first**. The user sees their
296
+ * recent work immediately on the dashboard. We deliberately do NOT
297
+ * walk backwards through older prompts — that would push the user's
298
+ * whole history onto the server on first install, which is
299
+ * unnecessary work and can blow past the per-batch payload limit.
300
+ * Anything older than the 100 newest stays local; subsequent
301
+ * syncs only pick up NEW prompts.
302
+ *
303
+ * 2. **Incremental** (`since` is a date): fetch prompts newer than
304
+ * the cursor, sorted **newest first** so the cursor advances to
305
+ * the actual latest prompt.
291
306
  */
292
307
  async getAllPrompts(since, limit = 100) {
293
308
  const sessions = await this.getSessions();
@@ -326,6 +341,9 @@ export class ClaudeCaptureService {
326
341
  seenHashes.add(prompt.hash);
327
342
  allPrompts.push(prompt);
328
343
  }
344
+ // Sort: newest first in both modes — ensures the cursor advances
345
+ // to the actual latest prompt and the server's `created_at` DESC
346
+ // sort puts the latest prompt at the top of the dashboard.
329
347
  allPrompts.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());
330
348
  return allPrompts.slice(0, limit);
331
349
  }
@@ -345,9 +345,18 @@ export class DaemonService {
345
345
  return this.status;
346
346
  }
347
347
  try {
348
- // Get prompts from Claude. Use a timestamp cursor to skip prompts older
349
- // than the last successful sync (server dedups, but skipping locally
350
- // saves bandwidth on subsequent syncs).
348
+ // Get prompts from Claude. The cursor controls which prompts we fetch:
349
+ //
350
+ // - First-ever run (no cursor yet): sync the LATEST 100 prompts so
351
+ // the user sees their recent work immediately. We deliberately
352
+ // do NOT walk backwards through older prompts — that would push
353
+ // the user's whole history onto the server on first install,
354
+ // which is unnecessary work and can blow past the per-batch
355
+ // payload limit. Anything older than the 100 newest stays local.
356
+ //
357
+ // - Subsequent runs (cursor set): fetch prompts newer than the
358
+ // cursor. This is normal incremental mode — only the latest
359
+ // new prompts get synced.
351
360
  const cursorIso = await this.configService.getLastSyncCursor();
352
361
  const since = cursorIso ? new Date(cursorIso) : undefined;
353
362
  const prompts = await this.captureService.getAllPrompts(since, MAX_PROMPTS_PER_SYNC);
@@ -379,12 +388,16 @@ export class DaemonService {
379
388
  const result = await this.apiService.syncPrompts(apiPrompts);
380
389
  this.status.lastSyncAt = new Date();
381
390
  this.status.promptsSynced += result.synced;
382
- // Persist the cursor at the newest prompt we ATTEMPTED to sync (not
383
- // just newly-synced ones). The server's content_hash dedup means we'll
384
- // see `result.synced: 0` on subsequent runs even though the prompts
385
- // are already saved that's normal. We want the cursor to advance
386
- // so the next run only fetches prompts newer than the newest one we've
387
- // seen, regardless of whether they were already on the server.
391
+ // Advance the cursor to the NEWEST prompt in the synced batch. This
392
+ // is correct in both modes:
393
+ //
394
+ // - First backfill: cursor = newest of the 100 batched → next
395
+ // cycle only picks up prompts strictly newer than that.
396
+ // - Incremental: cursor = newest of the new batch.
397
+ //
398
+ // The server's content_hash dedup means we never re-insert a
399
+ // prompt; advancing the cursor just means we don't re-fetch
400
+ // what we already have.
388
401
  if (prompts.length > 0) {
389
402
  const newest = prompts[0].timestamp;
390
403
  await this.configService.setLastSyncCursor(newest.toISOString());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "promptcase",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "CLI daemon to capture and sync AI prompts to PromptCase web app",
5
5
  "main": "dist/index.js",
6
6
  "bin": {