fluncle 0.235.0 → 0.237.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 +41 -8
- package/package.json +1 -1
package/bin/fluncle.mjs
CHANGED
|
@@ -622,7 +622,7 @@ function parseVersion(version) {
|
|
|
622
622
|
var currentVersion;
|
|
623
623
|
var init_version = __esm(() => {
|
|
624
624
|
init_output();
|
|
625
|
-
currentVersion = "0.
|
|
625
|
+
currentVersion = "0.237.0".trim() ? "0.237.0".trim() : "0.1.0";
|
|
626
626
|
});
|
|
627
627
|
|
|
628
628
|
// src/update-notifier.ts
|
|
@@ -2335,7 +2335,7 @@ function parseVersion2(version) {
|
|
|
2335
2335
|
var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
|
|
2336
2336
|
var init_version2 = __esm(() => {
|
|
2337
2337
|
init_output();
|
|
2338
|
-
currentVersion2 = "0.
|
|
2338
|
+
currentVersion2 = "0.237.0".trim() ? "0.237.0".trim() : "0.1.0";
|
|
2339
2339
|
});
|
|
2340
2340
|
|
|
2341
2341
|
// ../../packages/registry/src/index.ts
|
|
@@ -11433,7 +11433,7 @@ var init_admin_bios = __esm(() => {
|
|
|
11433
11433
|
});
|
|
11434
11434
|
|
|
11435
11435
|
// ../../packages/contracts/src/orpc/admin-catalogue.ts
|
|
11436
|
-
var CatalogueLensSchema, CapturePriorityReasonSchema, CatalogueMatchSchema, CatalogueTrackItemSchema, CatalogueSummarySchema, listCatalogueTracks, rankCatalogue, recordDemand, clearWrongAudio, requeueUnmatchedCaptures, requeueAnchor, flagWrongAudio, forceCapture, certifyTrack, setTrackDismissed, CaptureVerifyItemSchema, listUnverifiedCaptures, verifyCapture, CrawlPassSchema, CrawlPhaseInitializationSchema, CrawlPhaseInputSchema, CrawlPhaseOutputSchema, CrawlStatusSchema, crawlCatalogue, getCrawlStatus, ANCHOR_CANDIDATE_LIMIT = 100, ANCHOR_ARTIST_LIMIT = 20, ANCHOR_TEXT_MAX = 300, ANCHOR_ISRC_MAX = 64, ANCHOR_ID_MAX = 64, ANCHOR_URL_MAX = 2048, AnchorCandidateSchema, anchorTrack, DEEZER_CANDIDATE_LIMIT = 5, DEEZER_TEXT_MAX = 300, DEEZER_ISRC_MAX = 64, DEEZER_TRACK_ID_MAX = 32, DeezerIsrcCandidateSchema, resolveAnchor, resolveAnchorReview, setAnchorSearch, setAnchorApify, CaptureBudgetStateSchema, getCaptureBudget, setCaptureBudget, SpotifyAnchorBreakerStateSchema, getSpotifyAnchorBreaker, resetSpotifyAnchorBreaker, AppleBreakerStateSchema, resetAppleBreaker, adminCatalogueContract;
|
|
11436
|
+
var CatalogueLensSchema, CapturePriorityReasonSchema, CatalogueMatchSchema, CatalogueTrackItemSchema, CatalogueSummarySchema, listCatalogueTracks, rankCatalogue, recordDemand, clearWrongAudio, requeueUnmatchedCaptures, requeueAnchor, requeueIsrcRecovery, flagWrongAudio, forceCapture, certifyTrack, setTrackDismissed, CaptureVerifyItemSchema, listUnverifiedCaptures, verifyCapture, CrawlPassSchema, CrawlPhaseInitializationSchema, MAX_CRAWL_PREPARE_LIMIT = 6, CrawlPhaseInputSchema, CrawlPhaseOutputSchema, CrawlStatusSchema, crawlCatalogue, getCrawlStatus, ANCHOR_CANDIDATE_LIMIT = 100, ANCHOR_ARTIST_LIMIT = 20, ANCHOR_TEXT_MAX = 300, ANCHOR_ISRC_MAX = 64, ANCHOR_ID_MAX = 64, ANCHOR_URL_MAX = 2048, AnchorCandidateSchema, anchorTrack, DEEZER_CANDIDATE_LIMIT = 5, DEEZER_TEXT_MAX = 300, DEEZER_ISRC_MAX = 64, DEEZER_TRACK_ID_MAX = 32, DeezerIsrcCandidateSchema, resolveAnchor, resolveAnchorReview, setAnchorSearch, setAnchorApify, CaptureBudgetStateSchema, getCaptureBudget, setCaptureBudget, SpotifyAnchorBreakerStateSchema, getSpotifyAnchorBreaker, resetSpotifyAnchorBreaker, AppleBreakerStateSchema, resetAppleBreaker, adminCatalogueContract;
|
|
11437
11437
|
var init_admin_catalogue = __esm(() => {
|
|
11438
11438
|
init_dist3();
|
|
11439
11439
|
init_zod();
|
|
@@ -11562,6 +11562,21 @@ var init_admin_catalogue = __esm(() => {
|
|
|
11562
11562
|
summary: "Clear named rows' anchor re-ask backoff so the next tick retries them (operator)",
|
|
11563
11563
|
tags: ["Admin"]
|
|
11564
11564
|
}).input(object({ trackIds: array(string2().min(1)).min(1).max(250) })).output(object({ ok: literal(true), requeued: number2() }));
|
|
11565
|
+
requeueIsrcRecovery = oc.route({
|
|
11566
|
+
method: "POST",
|
|
11567
|
+
operationId: "requeueIsrcRecovery",
|
|
11568
|
+
path: "/admin/catalogue/isrc-recovery/requeue",
|
|
11569
|
+
summary: "Clear Deezer-empty ISRC-recovery stamps from a named window (operator)",
|
|
11570
|
+
tags: ["Admin"]
|
|
11571
|
+
}).input(object({
|
|
11572
|
+
dryRun: boolean2().default(true),
|
|
11573
|
+
since: string2().regex(/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d{1,3})?Z)?$/, "since must be an ISO date (2026-09-09) or instant (2026-09-09T00:00:00.000Z)")
|
|
11574
|
+
})).output(object({
|
|
11575
|
+
dryRun: boolean2(),
|
|
11576
|
+
matched: number2(),
|
|
11577
|
+
ok: literal(true),
|
|
11578
|
+
requeued: number2()
|
|
11579
|
+
}));
|
|
11565
11580
|
flagWrongAudio = oc.route({
|
|
11566
11581
|
method: "POST",
|
|
11567
11582
|
operationId: "flagWrongAudio",
|
|
@@ -11663,7 +11678,7 @@ var init_admin_catalogue = __esm(() => {
|
|
|
11663
11678
|
CrawlPhaseInputSchema = discriminatedUnion("phase", [
|
|
11664
11679
|
object({ phase: literal("initialize") }),
|
|
11665
11680
|
object({
|
|
11666
|
-
limit: number2().int().min(1).max(
|
|
11681
|
+
limit: number2().int().min(1).max(MAX_CRAWL_PREPARE_LIMIT).default(2),
|
|
11667
11682
|
maxHop: number2().int().min(0).max(3).default(2),
|
|
11668
11683
|
phase: literal("prepare")
|
|
11669
11684
|
}),
|
|
@@ -11686,7 +11701,7 @@ var init_admin_catalogue = __esm(() => {
|
|
|
11686
11701
|
object({
|
|
11687
11702
|
frontierPending: number2(),
|
|
11688
11703
|
initialization: CrawlPhaseInitializationSchema,
|
|
11689
|
-
items: array(object({ nodeId: string2(), preparedToken: string2() })).max(
|
|
11704
|
+
items: array(object({ nodeId: string2(), preparedToken: string2() })).max(MAX_CRAWL_PREPARE_LIMIT),
|
|
11690
11705
|
kind: _enum(["drained", "prepared", "unavailable"]),
|
|
11691
11706
|
ok: literal(true),
|
|
11692
11707
|
phase: literal("prepare")
|
|
@@ -11733,7 +11748,8 @@ var init_admin_catalogue = __esm(() => {
|
|
|
11733
11748
|
release: number2()
|
|
11734
11749
|
}),
|
|
11735
11750
|
labelsUndecided: number2(),
|
|
11736
|
-
seedLabels: array(string2())
|
|
11751
|
+
seedLabels: array(string2()),
|
|
11752
|
+
storablePending: number2()
|
|
11737
11753
|
}).meta({ id: "CrawlStatus" });
|
|
11738
11754
|
crawlCatalogue = oc.route({
|
|
11739
11755
|
inputStructure: "detailed",
|
|
@@ -11934,6 +11950,7 @@ var init_admin_catalogue = __esm(() => {
|
|
|
11934
11950
|
rank_catalogue: rankCatalogue,
|
|
11935
11951
|
record_demand: recordDemand,
|
|
11936
11952
|
requeue_anchor: requeueAnchor,
|
|
11953
|
+
requeue_isrc_recovery: requeueIsrcRecovery,
|
|
11937
11954
|
requeue_unmatched_captures: requeueUnmatchedCaptures,
|
|
11938
11955
|
reset_apple_breaker: resetAppleBreaker,
|
|
11939
11956
|
reset_spotify_anchor_breaker: resetSpotifyAnchorBreaker,
|
|
@@ -17235,10 +17252,10 @@ async function resolveDeezerSearch(track) {
|
|
|
17235
17252
|
return;
|
|
17236
17253
|
}
|
|
17237
17254
|
try {
|
|
17238
|
-
const query =
|
|
17255
|
+
const query = `${artist} ${stripVersionSuffix(track.title.trim())}`;
|
|
17239
17256
|
const response = await fetch(`https://api.deezer.com/search?q=${encodeURIComponent(query)}`);
|
|
17240
17257
|
const body = await response.json();
|
|
17241
|
-
const hit = (body.data ?? []).find((item) => item.preview && versionMatches(track.title, item.title ?? "") && baseTitleMatches(track.title, item.title ?? "") && durationAgrees(track.durationMs, item.duration));
|
|
17258
|
+
const hit = (body.data ?? []).find((item) => item.preview && normalize(item.artist?.name ?? "").includes(normalize(artist)) && versionMatches(track.title, item.title ?? "") && baseTitleMatches(track.title, item.title ?? "") && durationAgrees(track.durationMs, item.duration));
|
|
17242
17259
|
return downloadPreview(hit?.preview, "deezer:search");
|
|
17243
17260
|
} catch {
|
|
17244
17261
|
return;
|
|
@@ -18510,6 +18527,9 @@ async function requeueAnchorCommand(trackIds) {
|
|
|
18510
18527
|
trackIds
|
|
18511
18528
|
});
|
|
18512
18529
|
}
|
|
18530
|
+
async function requeueIsrcRecoveryCommand(input) {
|
|
18531
|
+
return adminApiPost("/api/v1/admin/catalogue/isrc-recovery/requeue", input);
|
|
18532
|
+
}
|
|
18513
18533
|
async function forceCaptureCommand(trackId) {
|
|
18514
18534
|
return adminApiPost("/api/v1/admin/catalogue/force-capture", {
|
|
18515
18535
|
trackId
|
|
@@ -22166,6 +22186,18 @@ JSON field reference:
|
|
|
22166
22186
|
}
|
|
22167
22187
|
console.log(`Re-queued ${requeued} of ${trackIds.length} row(s) \u2014 the next anchor tick picks them up at their real priority.`);
|
|
22168
22188
|
});
|
|
22189
|
+
catalogue.command("requeue-isrc-recovery").description("Clear Deezer-empty ISRC-recovery stamps from a window (dry-run; --apply to take)").requiredOption("--since <iso>", "Inclusive lower bound on the stamp (2026-09-09)").option("--apply", "Actually clear the stamps (default is a dry-run count)", false).option("--json", "Print JSON", false).action(async (options) => {
|
|
22190
|
+
await Promise.resolve().then(() => init_admin_catalogue2());
|
|
22191
|
+
const result = await requeueIsrcRecoveryCommand({
|
|
22192
|
+
dryRun: options.apply !== true,
|
|
22193
|
+
since: options.since
|
|
22194
|
+
});
|
|
22195
|
+
if (options.json) {
|
|
22196
|
+
printJson({ ok: true, ...result });
|
|
22197
|
+
return;
|
|
22198
|
+
}
|
|
22199
|
+
console.log(result.dryRun ? `DRY RUN \u2014 ${result.matched} row(s) stamped Deezer-empty since ${options.since}. Re-run with --apply to clear them.` : `Cleared ${result.requeued} of ${result.matched} row(s) \u2014 the next isrc-recovery tick asks them again.`);
|
|
22200
|
+
});
|
|
22169
22201
|
catalogue.command("requeue-unmatched").description("Re-queue terminal-unmatched captures after a matcher improvement (operator)").option("--json", "Print JSON", false).action(async (options) => {
|
|
22170
22202
|
await Promise.resolve().then(() => init_admin_catalogue2());
|
|
22171
22203
|
const { requeued, skippedVetoed } = await requeueUnmatchedCommand();
|
|
@@ -22904,6 +22936,7 @@ async function runCrawlStatus(options, crawlStatusCommand) {
|
|
|
22904
22936
|
const { frontier, frontierByKind } = result;
|
|
22905
22937
|
console.log(`Catalogue: ${result.catalogueTracks} uncertified track(s); ${result.anchorsPending} awaiting a Spotify anchor.`);
|
|
22906
22938
|
console.log(`Frontier: ${frontier.pending} pending, ${frontier.done} done, ${frontier.failed} failed, ${frontier.skipped} skipped (${frontierByKind.label} label, ${frontierByKind.artist} artist, ${frontierByKind.release} release).`);
|
|
22939
|
+
console.log(`Ready to write: ${result.storablePending} storable release node(s) claimable now.`);
|
|
22907
22940
|
console.log(`Seeds (${result.seedLabels.length}): ${result.seedLabels.join(", ") || "none enabled"}.`);
|
|
22908
22941
|
console.log(`Awaiting your ruling: ${result.labelsUndecided} label(s).`);
|
|
22909
22942
|
}
|
package/package.json
CHANGED