fluncle 0.214.0 → 0.216.0
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/bin/fluncle.mjs +89 -4
- package/package.json +1 -1
package/bin/fluncle.mjs
CHANGED
|
@@ -610,7 +610,7 @@ function parseVersion(version) {
|
|
|
610
610
|
var currentVersion;
|
|
611
611
|
var init_version = __esm(() => {
|
|
612
612
|
init_output();
|
|
613
|
-
currentVersion = "0.
|
|
613
|
+
currentVersion = "0.216.0".trim() ? "0.216.0".trim() : "0.1.0";
|
|
614
614
|
});
|
|
615
615
|
|
|
616
616
|
// src/update-notifier.ts
|
|
@@ -2452,7 +2452,7 @@ function parseVersion2(version) {
|
|
|
2452
2452
|
var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
|
|
2453
2453
|
var init_version2 = __esm(() => {
|
|
2454
2454
|
init_output();
|
|
2455
|
-
currentVersion2 = "0.
|
|
2455
|
+
currentVersion2 = "0.216.0".trim() ? "0.216.0".trim() : "0.1.0";
|
|
2456
2456
|
});
|
|
2457
2457
|
|
|
2458
2458
|
// ../../packages/registry/src/index.ts
|
|
@@ -3550,6 +3550,22 @@ var init_src = __esm(() => {
|
|
|
3550
3550
|
title: "Spotify anchors",
|
|
3551
3551
|
weights: { status: "hidden" }
|
|
3552
3552
|
},
|
|
3553
|
+
{
|
|
3554
|
+
exposedContent: [
|
|
3555
|
+
"mirror the anchored, explicitly allowlisted public catalogue into the shared read-only device replica"
|
|
3556
|
+
],
|
|
3557
|
+
kind: "cron",
|
|
3558
|
+
name: "cron.device-mirror",
|
|
3559
|
+
operatorNotes: "hourly, run by a host systemd timer (docs/agents/hermes/device-mirror-timer/). Reads one consistent anchored-cut snapshot through a read-only source credential, diffs every whitelisted tuple against the shared device database, then applies dependent-first deletes and parent-first upserts in bounded parameterized batches. The target is mutated IN PLACE: rebuilding it would reset the libSQL replication log and force every device to bootstrap the full database again. A schema-version mismatch stops for an operator migration; the content fingerprint and derived timestamp update only after a verified zero-drift tick. Zero LLM tokens. Source: docs/agents/hermes/scripts/device-mirror.*. See docs/planning/offline-first-mobile-research.md.",
|
|
3560
|
+
probeConfig: {
|
|
3561
|
+
cadenceMs: 60 * MINUTE_MS,
|
|
3562
|
+
cronName: "fluncle-device-mirror",
|
|
3563
|
+
kind: "cron"
|
|
3564
|
+
},
|
|
3565
|
+
statusDescription: "keeps the offline catalogue replica in step",
|
|
3566
|
+
title: "Device catalogue mirror",
|
|
3567
|
+
weights: { status: "hidden" }
|
|
3568
|
+
},
|
|
3553
3569
|
{
|
|
3554
3570
|
command: "fluncle admin frontier refresh",
|
|
3555
3571
|
exposedContent: [
|
|
@@ -3781,9 +3797,9 @@ var init_src = __esm(() => {
|
|
|
3781
3797
|
weights: { status: "hidden" }
|
|
3782
3798
|
},
|
|
3783
3799
|
{
|
|
3784
|
-
command: "fluncle admin backfills discogs && fluncle admin backfills lastfm && fluncle admin backfills apple-music && fluncle admin backfills apple-catalogue",
|
|
3800
|
+
command: "fluncle admin backfills discogs && fluncle admin backfills lastfm && fluncle admin backfills apple-music && fluncle admin backfills apple-catalogue && fluncle admin backfills beatport && fluncle admin backfills discogs-facts",
|
|
3785
3801
|
exposedContent: [
|
|
3786
|
-
"Discogs id + Last.fm love + Apple Music link repair, findings then catalogue (--no-agent, Worker HTTP)"
|
|
3802
|
+
"Discogs id + Last.fm love + Apple Music link + Beatport link repair, findings then catalogue, then each record's catalogue number (--no-agent, Worker HTTP)"
|
|
3787
3803
|
],
|
|
3788
3804
|
kind: "cron",
|
|
3789
3805
|
name: "cron.backfill",
|
|
@@ -4712,6 +4728,7 @@ __export(exports_admin_tracks, {
|
|
|
4712
4728
|
captureQueueCommand: () => captureQueueCommand,
|
|
4713
4729
|
backfillRecordingMbidsCommand: () => backfillRecordingMbidsCommand,
|
|
4714
4730
|
backfillLastfmCommand: () => backfillLastfmCommand,
|
|
4731
|
+
backfillDiscogsFactsCommand: () => backfillDiscogsFactsCommand,
|
|
4715
4732
|
backfillDiscogsCommand: () => backfillDiscogsCommand,
|
|
4716
4733
|
backfillBeatportCommand: () => backfillBeatportCommand,
|
|
4717
4734
|
backfillArtistEdgesCommand: () => backfillArtistEdgesCommand,
|
|
@@ -4897,6 +4914,10 @@ async function backfillAppleMusicCommand(limit, dryRun, cursor) {
|
|
|
4897
4914
|
}
|
|
4898
4915
|
return adminApiPost(`/api/v1/admin/backfill/apple-music?${params.toString()}`);
|
|
4899
4916
|
}
|
|
4917
|
+
async function backfillDiscogsFactsCommand(limit, dryRun) {
|
|
4918
|
+
const params = new URLSearchParams({ dryRun: String(dryRun), limit: String(limit) });
|
|
4919
|
+
return adminApiPost(`/api/v1/admin/backfill/discogs-facts?${params.toString()}`);
|
|
4920
|
+
}
|
|
4900
4921
|
async function backfillBeatportCommand(limit, dryRun, cursor) {
|
|
4901
4922
|
const params = new URLSearchParams({ dryRun: String(dryRun), limit: String(limit) });
|
|
4902
4923
|
if (cursor) {
|
|
@@ -10470,6 +10491,10 @@ JSON field reference:
|
|
|
10470
10491
|
const { backfillDiscogsCommand: backfillDiscogsCommand2 } = await Promise.resolve().then(() => (init_admin_tracks(), exports_admin_tracks));
|
|
10471
10492
|
await runBackfillDiscogs(options, backfillDiscogsCommand2);
|
|
10472
10493
|
});
|
|
10494
|
+
backfill.command("discogs-facts").description("Read album catalogue numbers + styles from already-resolved Discogs releases").option("--dry-run", "Report the eligible albums without reading Discogs or writing", false).option("--limit <limit>", "Max albums to read", "50").option("--json", "Print JSON", false).action(async (options) => {
|
|
10495
|
+
const { backfillDiscogsFactsCommand: backfillDiscogsFactsCommand2 } = await Promise.resolve().then(() => (init_admin_tracks(), exports_admin_tracks));
|
|
10496
|
+
await runBackfillDiscogsFacts(options, backfillDiscogsFactsCommand2);
|
|
10497
|
+
});
|
|
10473
10498
|
backfill.command("apple-music").description("Resolve missing Apple Music URLs for published findings (exact ISRC match)").option("--dry-run", "Report the eligible set without resolving or writing", false).option("--limit <limit>", "Max findings to resolve", "50").option("--json", "Print JSON", false).action(async (options) => {
|
|
10474
10499
|
const { backfillAppleMusicCommand: backfillAppleMusicCommand2 } = await Promise.resolve().then(() => (init_admin_tracks(), exports_admin_tracks));
|
|
10475
10500
|
await runBackfillAppleMusic(options, backfillAppleMusicCommand2);
|
|
@@ -11267,6 +11292,63 @@ async function runBackfillAppleCatalogue(options, backfillAppleCatalogueCommand2
|
|
|
11267
11292
|
process.exitCode = 1;
|
|
11268
11293
|
}
|
|
11269
11294
|
}
|
|
11295
|
+
async function runBackfillDiscogsFacts(options, backfillDiscogsFactsCommand2) {
|
|
11296
|
+
const limit = parseListLimit(options.limit);
|
|
11297
|
+
const resolved = [];
|
|
11298
|
+
const none = [];
|
|
11299
|
+
const failed = [];
|
|
11300
|
+
let dryRun = options.dryRun;
|
|
11301
|
+
let throttled = false;
|
|
11302
|
+
let configured = true;
|
|
11303
|
+
while (resolved.length + none.length + failed.length < limit) {
|
|
11304
|
+
const remaining = limit - (resolved.length + none.length + failed.length);
|
|
11305
|
+
const result = await backfillDiscogsFactsCommand2(remaining, options.dryRun);
|
|
11306
|
+
dryRun = result.dryRun;
|
|
11307
|
+
configured = result.configured;
|
|
11308
|
+
resolved.push(...result.resolved);
|
|
11309
|
+
none.push(...result.none);
|
|
11310
|
+
failed.push(...result.failed);
|
|
11311
|
+
if (!options.json) {
|
|
11312
|
+
const verb2 = result.dryRun ? "would read" : "read";
|
|
11313
|
+
console.log(` \u2026${verb2} ${result.resolvedCount} catalogue number(s); ${result.noneCount} with none; ${result.failedCount} failed`);
|
|
11314
|
+
}
|
|
11315
|
+
if (!result.configured) {
|
|
11316
|
+
break;
|
|
11317
|
+
}
|
|
11318
|
+
if (result.rateLimited) {
|
|
11319
|
+
throttled = true;
|
|
11320
|
+
break;
|
|
11321
|
+
}
|
|
11322
|
+
if (result.resolvedCount === 0 && result.noneCount === 0 && result.failedCount === 0) {
|
|
11323
|
+
break;
|
|
11324
|
+
}
|
|
11325
|
+
}
|
|
11326
|
+
if (options.json) {
|
|
11327
|
+
printSweepJson({
|
|
11328
|
+
configured,
|
|
11329
|
+
dryRun,
|
|
11330
|
+
failed,
|
|
11331
|
+
none,
|
|
11332
|
+
noneCount: none.length,
|
|
11333
|
+
rateLimited: throttled,
|
|
11334
|
+
resolved,
|
|
11335
|
+
resolvedCount: resolved.length
|
|
11336
|
+
}, failed.length);
|
|
11337
|
+
return;
|
|
11338
|
+
}
|
|
11339
|
+
if (!configured) {
|
|
11340
|
+
console.log("Discogs facts backfill is not configured (the Worker's DISCOGS_USER_TOKEN is unset) \u2014 nothing read.");
|
|
11341
|
+
return;
|
|
11342
|
+
}
|
|
11343
|
+
const verb = dryRun ? "Would read" : "Read";
|
|
11344
|
+
console.log(`${verb} ${resolved.length} catalogue number(s); ${none.length} release(s) carry none; ${failed.length} failed.`);
|
|
11345
|
+
for (const item of failed) {
|
|
11346
|
+
console.log(` ${item.slug}: ${item.error}`);
|
|
11347
|
+
}
|
|
11348
|
+
if (failed.length > 0) {
|
|
11349
|
+
process.exitCode = 1;
|
|
11350
|
+
}
|
|
11351
|
+
}
|
|
11270
11352
|
async function runBackfillArtists(options, backfillArtistsCommand2) {
|
|
11271
11353
|
const limit = parseListLimit(options.limit);
|
|
11272
11354
|
const upserted = [];
|
|
@@ -11608,6 +11690,7 @@ async function runBackfillArtistEdges(options, backfillArtistEdgesCommand2) {
|
|
|
11608
11690
|
let cursor;
|
|
11609
11691
|
let dryRun = options.dryRun;
|
|
11610
11692
|
let edgesWritten = 0;
|
|
11693
|
+
let queueDepth = 0;
|
|
11611
11694
|
let scanned = 0;
|
|
11612
11695
|
let unmatchedNames = 0;
|
|
11613
11696
|
while (scanned < limit) {
|
|
@@ -11620,6 +11703,7 @@ async function runBackfillArtistEdges(options, backfillArtistEdgesCommand2) {
|
|
|
11620
11703
|
fullyMatched.push(...result.fullyMatched);
|
|
11621
11704
|
partiallyMatched.push(...result.partiallyMatched);
|
|
11622
11705
|
zeroMatched.push(...result.zeroMatched);
|
|
11706
|
+
queueDepth = result.queueDepth;
|
|
11623
11707
|
if (!options.json) {
|
|
11624
11708
|
const verb2 = result.dryRun ? "would write" : "wrote";
|
|
11625
11709
|
console.log(` \u2026visited ${result.scanned}; ${verb2} ${result.edgesWritten} edge(s); ${result.fullyMatchedCount} full, ${result.partiallyMatchedCount} partial, ${result.zeroMatchedCount} zero; ${result.unmatchedNames} name(s) unmatched`);
|
|
@@ -11638,6 +11722,7 @@ async function runBackfillArtistEdges(options, backfillArtistEdgesCommand2) {
|
|
|
11638
11722
|
ok: true,
|
|
11639
11723
|
partiallyMatched,
|
|
11640
11724
|
partiallyMatchedCount: partiallyMatched.length,
|
|
11725
|
+
queueDepth,
|
|
11641
11726
|
scanned,
|
|
11642
11727
|
unmatchedNames,
|
|
11643
11728
|
zeroMatched,
|
package/package.json
CHANGED