fluncle 0.238.0 → 0.239.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.
Files changed (2) hide show
  1. package/bin/fluncle.mjs +28 -5
  2. 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.238.0".trim() ? "0.238.0".trim() : "0.1.0";
625
+ currentVersion = "0.239.0".trim() ? "0.239.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.238.0".trim() ? "0.238.0".trim() : "0.1.0";
2338
+ currentVersion2 = "0.239.0".trim() ? "0.239.0".trim() : "0.1.0";
2339
2339
  });
2340
2340
 
2341
2341
  // ../../packages/registry/src/index.ts
@@ -11435,7 +11435,7 @@ var init_admin_bios = __esm(() => {
11435
11435
  });
11436
11436
 
11437
11437
  // ../../packages/contracts/src/orpc/admin-catalogue.ts
11438
- 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;
11438
+ 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, AnchorRungFlagsSchema, getSpotifyAnchorBreaker, resetSpotifyAnchorBreaker, AppleBreakerStateSchema, resetAppleBreaker, adminCatalogueContract;
11439
11439
  var init_admin_catalogue = __esm(() => {
11440
11440
  init_dist3();
11441
11441
  init_zod();
@@ -11841,7 +11841,9 @@ var init_admin_catalogue = __esm(() => {
11841
11841
  source: _enum(["listenbrainz", "spotify-isrc", "spotify-search"]).nullable(),
11842
11842
  spotifyIsrcAsked: boolean2(),
11843
11843
  spotifySearchDone: boolean2(),
11844
+ spotifySearchEnabled: boolean2(),
11844
11845
  spotifyThrottled: boolean2(),
11846
+ stamped: boolean2(),
11845
11847
  verifiedBy: _enum(["isrc", "search", "search-subset"]).nullable()
11846
11848
  }));
11847
11849
  resolveAnchorReview = oc.route({
@@ -11910,13 +11912,17 @@ var init_admin_catalogue = __esm(() => {
11910
11912
  tripped: boolean2(),
11911
11913
  trippedAt: string2().nullable()
11912
11914
  }).meta({ id: "SpotifyAnchorBreakerState" });
11915
+ AnchorRungFlagsSchema = object({
11916
+ apifyEnabled: boolean2(),
11917
+ spotifySearchEnabled: boolean2()
11918
+ }).meta({ id: "AnchorRungFlags" });
11913
11919
  getSpotifyAnchorBreaker = oc.route({
11914
11920
  method: "GET",
11915
11921
  operationId: "getSpotifyAnchorBreaker",
11916
11922
  path: "/admin/catalogue/anchor/breaker",
11917
- summary: "The Spotify anchor-search throttle breaker: tripped, why, and how long left",
11923
+ summary: "The Spotify anchor-search throttle breaker: tripped, why, how long left, and the rungs",
11918
11924
  tags: ["Admin"]
11919
- }).input(object({})).output(SpotifyAnchorBreakerStateSchema.extend({ ok: literal(true) }));
11925
+ }).input(object({})).output(SpotifyAnchorBreakerStateSchema.extend({ ok: literal(true), rungs: AnchorRungFlagsSchema }));
11920
11926
  resetSpotifyAnchorBreaker = oc.route({
11921
11927
  method: "POST",
11922
11928
  operationId: "resetSpotifyAnchorBreaker",
@@ -18532,6 +18538,9 @@ async function requeueAnchorCommand(trackIds) {
18532
18538
  async function requeueIsrcRecoveryCommand(input) {
18533
18539
  return adminApiPost("/api/v1/admin/catalogue/isrc-recovery/requeue", input);
18534
18540
  }
18541
+ async function anchorBreakerCommand() {
18542
+ return adminApiGet("/api/v1/admin/catalogue/anchor/breaker");
18543
+ }
18535
18544
  async function forceCaptureCommand(trackId) {
18536
18545
  return adminApiPost("/api/v1/admin/catalogue/force-capture", {
18537
18546
  trackId
@@ -22189,6 +22198,20 @@ JSON field reference:
22189
22198
  }
22190
22199
  console.log(`Re-queued ${requeued} of ${trackIds.length} row(s) \u2014 the next anchor tick picks them up at their real priority.`);
22191
22200
  });
22201
+ catalogue.command("anchor-breaker").description("Why the anchor rungs are quiet: the throttle breaker, and which rungs are armed").option("--json", "Print JSON", false).action(async (options) => {
22202
+ await Promise.resolve().then(() => init_admin_catalogue2());
22203
+ const state = await anchorBreakerCommand();
22204
+ if (options.json) {
22205
+ printJson({ ...state, ok: true });
22206
+ return;
22207
+ }
22208
+ const minutes = Math.ceil(state.cooldownRemainingMs / 60000);
22209
+ console.log(state.tripped ? `BREAKER TRIPPED \u2014 ${state.reason ?? "unknown"}, ~${minutes}m left (${state.throttlesInWindow} throttle(s) in window)` : `BREAKER CLEAR \u2014 ${state.throttlesInWindow} throttle(s) in window`);
22210
+ console.log(`RUNGS \u2014 spotify search ${state.rungs.spotifySearchEnabled ? "ARMED" : "OFF"} \xB7 apify fallback ${state.rungs.apifyEnabled ? "ARMED" : "OFF"}`);
22211
+ if (!state.rungs.spotifySearchEnabled && !state.rungs.apifyEnabled) {
22212
+ console.log("No rung can conclude \u2014 ListenBrainz still runs and can win, but its miss settles nothing.");
22213
+ }
22214
+ });
22192
22215
  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) => {
22193
22216
  await Promise.resolve().then(() => init_admin_catalogue2());
22194
22217
  const result = await requeueIsrcRecoveryCommand({
package/package.json CHANGED
@@ -31,5 +31,5 @@
31
31
  "url": "git+https://github.com/mauricekleine/fluncle.git"
32
32
  },
33
33
  "type": "module",
34
- "version": "0.238.0"
34
+ "version": "0.239.0"
35
35
  }