fluncle 0.260.0 → 0.262.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 +107 -14
- 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.262.0".trim() ? "0.262.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.262.0".trim() ? "0.262.0".trim() : "0.1.0";
|
|
2339
2339
|
});
|
|
2340
2340
|
|
|
2341
2341
|
// ../../packages/registry/src/index.ts
|
|
@@ -3434,7 +3434,7 @@ var init_src = __esm(() => {
|
|
|
3434
3434
|
],
|
|
3435
3435
|
kind: "cron",
|
|
3436
3436
|
name: "cron.cluster",
|
|
3437
|
-
operatorNotes: "nightly (
|
|
3437
|
+
operatorNotes: "nightly (03:20 Amsterdam), run by a Hermes host systemd timer (docs/agents/hermes/cluster-timer/). Assignment-ONLY + idempotent (a no-op on an unchanged corpus): assign each finding to its nearest stored centroid, recompute centroids as members' means, retire an emptied galaxy, consume an operator split_requested_at (a k=2 fit). Zero LLM tokens; sub-second CPU. A full k=9 fit is an OPERATOR act (--cold-start / --remint), never scheduled. Source: docs/agents/hermes/scripts/cluster-sweep.* + cluster.py. See docs/agents/cluster-engine.md.",
|
|
3438
3438
|
probeConfig: { cadenceMs: 24 * 60 * MINUTE_MS, cronName: "fluncle-cluster", kind: "cron" },
|
|
3439
3439
|
statusDescription: "groups the archive into sonic galaxies",
|
|
3440
3440
|
title: "Sonic galaxies",
|
|
@@ -3459,11 +3459,12 @@ var init_src = __esm(() => {
|
|
|
3459
3459
|
],
|
|
3460
3460
|
kind: "cron",
|
|
3461
3461
|
name: "cron.label-releases",
|
|
3462
|
-
operatorNotes: "every
|
|
3462
|
+
operatorNotes: "every 15 minutes from 03:00 through 08:45 UTC, run by a Hermes host systemd timer (docs/agents/hermes/label-releases-timer/). The FRESHNESS TAP (D8): MusicBrainz WALKS the graph (cron.crawl) but lags a release ~2 weeks; Spotify has it day one, so this mints METADATA-ONLY catalogue rows (a `tracks` row with no `findings` row) for each ENABLED seed label's fresh releases with their real dates — closing the /fresh lag cliff. The WORKER does all of it (`backfill_label_releases`, agent tier): it searches the official Spotify API (`label:\"<name>\" tag:new`), reads each hit as a SINGLE `GET /albums/{id}` then `GET /tracks/{id}` (the batch endpoints are 403 at our tier), and mints. The box sweep is a thin HTTP TRIGGER that POSTs bounded passes with the agent token — no vendor token, no CLI dependency (a pinned box CLI missing a flag broke an earlier run). The gate, both required: artist-grounding (an album's Spotify artist already in `artists.spotify_artist_id` — the PRIMARY anchor that stops cross-genre homonym junk) AND an EXACT fold-match of the seed name in the ℗/© copyright; an album with no release_date is dropped outright (/fresh could never show it). BUDGET: the tap shares the official app's per-app window with the user-facing paths, so it paces itself against the shared call meter and stops at a FRACTION of the window (its own ceiling) — user write paths get the window, the tap takes only slack. Hitting that ceiling ends the pass cleanly and the durable per-label cadence stamps resume it next tick. It certifies nothing, publishes nothing, never widens the graph (no new labels, no artist hops). Deduped against the MB crawl from both directions (Spotify id/uri/ISRC + same-album title fold). No vendor spend and zero LLM tokens. Source: docs/agents/hermes/scripts/label-releases-sweep.*. See docs/catalogue-crawler.md.",
|
|
3463
3463
|
probeConfig: {
|
|
3464
3464
|
cadenceMs: 24 * 60 * MINUTE_MS,
|
|
3465
3465
|
cronName: "fluncle-label-releases",
|
|
3466
|
-
kind: "cron"
|
|
3466
|
+
kind: "cron",
|
|
3467
|
+
schedule: { time: "03:00", tz: "UTC" }
|
|
3467
3468
|
},
|
|
3468
3469
|
statusDescription: "taps day-one releases from the enabled labels",
|
|
3469
3470
|
title: "Freshness tap",
|
|
@@ -10192,11 +10193,11 @@ var init_zod = __esm(() => {
|
|
|
10192
10193
|
});
|
|
10193
10194
|
|
|
10194
10195
|
// ../../packages/contracts/src/orpc/admin-catalogue.ts
|
|
10195
|
-
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, CrawlFetchPlanSchema, SuppliedCrawlBodySchema, MAX_CRAWL_COMMIT_BATCH, CRAWL_COMMIT_TOKEN_MAX_BYTES, CRAWL_COMMIT_BATCH_MAX_TOTAL_BYTES, CrawlCommitItemSchema, CrawlCommitReceiptSchema, CrawlPhaseCapabilitiesSchema, CrawlPhaseInputSchema, CrawlPhaseOutputSchema, CrawlStatusSchema, CrawlPipelineSummarySchema, crawlCatalogue, commitCrawlNodes, 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, recordAnchorFailure, 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, AnchorApifyBudgetSchema, getAnchorApifyBudget, setAnchorApifyBudget, SpotifyAnchorBreakerStateSchema, AnchorRungFlagsSchema, getSpotifyAnchorBreaker, resetSpotifyAnchorBreaker, AppleBreakerStateSchema, resetAppleBreaker, adminCatalogueContract;
|
|
10196
|
+
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, CrawlFetchPlanSchema, SuppliedCrawlBodySchema, MAX_CRAWL_COMMIT_BATCH, CRAWL_COMMIT_TOKEN_MAX_BYTES, CRAWL_COMMIT_BATCH_MAX_TOTAL_BYTES, CrawlCommitItemSchema, CrawlCommitReceiptSchema, CrawlPhaseCapabilitiesSchema, CrawlPhaseInputSchema, CrawlPhaseOutputSchema, CrawlStatusSchema, CrawlPipelineSummarySchema, PipelineWatchBoundedCountSchema, getPipeline, crawlCatalogue, commitCrawlNodes, 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, recordAnchorFailure, 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, AnchorApifyBudgetSchema, getAnchorApifyBudget, setAnchorApifyBudget, SpotifyAnchorBreakerStateSchema, AnchorRungFlagsSchema, getSpotifyAnchorBreaker, LabelReleasesBudgetSchema, getLabelReleasesBudget, setLabelReleasesBudget, resetSpotifyAnchorBreaker, AppleBreakerStateSchema, resetAppleBreaker, adminCatalogueContract;
|
|
10196
10197
|
var init_admin_catalogue = __esm(() => {
|
|
10197
10198
|
init_dist3();
|
|
10198
10199
|
init_zod();
|
|
10199
|
-
CatalogueLensSchema = _enum(["capture", "dismissed", "ear", "failed", "quarantine", "unmatched"]).meta({ id: "CatalogueLens" });
|
|
10200
|
+
CatalogueLensSchema = _enum(["capture", "dismissed", "ear", "failed", "long", "quarantine", "unmatched"]).meta({ id: "CatalogueLens" });
|
|
10200
10201
|
CapturePriorityReasonSchema = object({
|
|
10201
10202
|
kind: _enum(["artist", "label", "none", "seed-label", "skipped-label", "unauthorized"]),
|
|
10202
10203
|
name: string2().nullable()
|
|
@@ -10220,6 +10221,7 @@ var init_admin_catalogue = __esm(() => {
|
|
|
10220
10221
|
duplicateOf: CatalogueMatchSchema.nullable(),
|
|
10221
10222
|
hasCapturedAudio: boolean2(),
|
|
10222
10223
|
hasPreview: boolean2(),
|
|
10224
|
+
hiddenFromPublic: boolean2(),
|
|
10223
10225
|
isrc: string2().nullable(),
|
|
10224
10226
|
key: string2().nullable(),
|
|
10225
10227
|
label: string2().nullable(),
|
|
@@ -10582,6 +10584,21 @@ var init_admin_catalogue = __esm(() => {
|
|
|
10582
10584
|
summary: literal(true),
|
|
10583
10585
|
unstorablePending: number2()
|
|
10584
10586
|
}).meta({ id: "CrawlPipelineSummary" });
|
|
10587
|
+
PipelineWatchBoundedCountSchema = object({ atLeast: boolean2(), count: number2().int().nonnegative() }).meta({ id: "PipelineWatchBoundedCount" });
|
|
10588
|
+
getPipeline = oc.route({
|
|
10589
|
+
method: "GET",
|
|
10590
|
+
operationId: "getPipeline",
|
|
10591
|
+
path: "/admin/catalogue/pipeline",
|
|
10592
|
+
summary: "Bounded pipeline counts for the box watchdog",
|
|
10593
|
+
tags: ["Admin"]
|
|
10594
|
+
}).input(object({})).output(object({
|
|
10595
|
+
anchors: PipelineWatchBoundedCountSchema,
|
|
10596
|
+
capture: PipelineWatchBoundedCountSchema.nullable(),
|
|
10597
|
+
frontier: PipelineWatchBoundedCountSchema,
|
|
10598
|
+
ok: literal(true),
|
|
10599
|
+
storable: PipelineWatchBoundedCountSchema,
|
|
10600
|
+
unstorable: PipelineWatchBoundedCountSchema
|
|
10601
|
+
}));
|
|
10585
10602
|
crawlCatalogue = oc.route({
|
|
10586
10603
|
inputStructure: "detailed",
|
|
10587
10604
|
method: "POST",
|
|
@@ -10809,7 +10826,30 @@ var init_admin_catalogue = __esm(() => {
|
|
|
10809
10826
|
path: "/admin/catalogue/anchor/breaker",
|
|
10810
10827
|
summary: "The Spotify anchor-search throttle breaker: tripped, why, how long left, and the rungs",
|
|
10811
10828
|
tags: ["Admin"]
|
|
10812
|
-
}).input(object({})).output(SpotifyAnchorBreakerStateSchema.extend({
|
|
10829
|
+
}).input(object({})).output(SpotifyAnchorBreakerStateSchema.extend({
|
|
10830
|
+
ok: literal(true),
|
|
10831
|
+
rungs: AnchorRungFlagsSchema,
|
|
10832
|
+
spotifyDailyCalls: number2().int().nullable()
|
|
10833
|
+
}));
|
|
10834
|
+
LabelReleasesBudgetSchema = object({
|
|
10835
|
+
callsSpent: number2().int().nonnegative(),
|
|
10836
|
+
dailyBudget: number2().int().nonnegative(),
|
|
10837
|
+
spotifyDailyCalls: number2().int().nonnegative()
|
|
10838
|
+
});
|
|
10839
|
+
getLabelReleasesBudget = oc.route({
|
|
10840
|
+
method: "GET",
|
|
10841
|
+
operationId: "getLabelReleasesBudget",
|
|
10842
|
+
path: "/admin/catalogue/label-releases-budget",
|
|
10843
|
+
summary: "Read the label releases tap daily budget and Spotify usage",
|
|
10844
|
+
tags: ["Admin"]
|
|
10845
|
+
}).input(object({})).output(LabelReleasesBudgetSchema.extend({ ok: literal(true) }));
|
|
10846
|
+
setLabelReleasesBudget = oc.route({
|
|
10847
|
+
method: "PUT",
|
|
10848
|
+
operationId: "setLabelReleasesBudget",
|
|
10849
|
+
path: "/admin/catalogue/label-releases-budget",
|
|
10850
|
+
summary: "Set the label releases tap daily budget (operator)",
|
|
10851
|
+
tags: ["Admin"]
|
|
10852
|
+
}).input(object({ dailyBudget: number2().int().min(0).max(1e6) })).output(LabelReleasesBudgetSchema.extend({ ok: literal(true) }));
|
|
10813
10853
|
resetSpotifyAnchorBreaker = oc.route({
|
|
10814
10854
|
method: "POST",
|
|
10815
10855
|
operationId: "resetSpotifyAnchorBreaker",
|
|
@@ -10841,6 +10881,8 @@ var init_admin_catalogue = __esm(() => {
|
|
|
10841
10881
|
get_anchor_apify_budget: getAnchorApifyBudget,
|
|
10842
10882
|
get_capture_budget: getCaptureBudget,
|
|
10843
10883
|
get_crawl_status: getCrawlStatus,
|
|
10884
|
+
get_label_releases_budget: getLabelReleasesBudget,
|
|
10885
|
+
get_pipeline: getPipeline,
|
|
10844
10886
|
get_spotify_anchor_breaker: getSpotifyAnchorBreaker,
|
|
10845
10887
|
list_catalogue_tracks: listCatalogueTracks,
|
|
10846
10888
|
list_unverified_captures: listUnverifiedCaptures,
|
|
@@ -10858,6 +10900,7 @@ var init_admin_catalogue = __esm(() => {
|
|
|
10858
10900
|
set_anchor_apify_budget: setAnchorApifyBudget,
|
|
10859
10901
|
set_anchor_search: setAnchorSearch,
|
|
10860
10902
|
set_capture_budget: setCaptureBudget,
|
|
10903
|
+
set_label_releases_budget: setLabelReleasesBudget,
|
|
10861
10904
|
set_track_dismissed: setTrackDismissed,
|
|
10862
10905
|
verify_capture: verifyCapture
|
|
10863
10906
|
};
|
|
@@ -11910,6 +11953,13 @@ var init_admin_backfills = __esm(() => {
|
|
|
11910
11953
|
})).output(object({
|
|
11911
11954
|
albumsMatched: number2(),
|
|
11912
11955
|
albumsSeen: number2(),
|
|
11956
|
+
blockedReason: _enum([
|
|
11957
|
+
"spotify_breaker",
|
|
11958
|
+
"spotify_budget",
|
|
11959
|
+
"spotify_budget_spent",
|
|
11960
|
+
"spotify_quota",
|
|
11961
|
+
"spotify_throttle"
|
|
11962
|
+
]).nullable(),
|
|
11913
11963
|
budgetPaused: boolean2(),
|
|
11914
11964
|
configured: boolean2(),
|
|
11915
11965
|
dryRun: boolean2(),
|
|
@@ -11917,14 +11967,20 @@ var init_admin_backfills = __esm(() => {
|
|
|
11917
11967
|
failedLabels: array(string2()),
|
|
11918
11968
|
fetchCeilingHit: boolean2(),
|
|
11919
11969
|
labelSlugs: array(string2()),
|
|
11970
|
+
labelsDue: number2(),
|
|
11920
11971
|
labelsProbed: number2(),
|
|
11972
|
+
neverChecked: number2(),
|
|
11921
11973
|
newRows: number2(),
|
|
11922
11974
|
newTrackIds: array(string2()),
|
|
11923
11975
|
ok: literal(true),
|
|
11976
|
+
quotaExceeded: boolean2(),
|
|
11924
11977
|
rateLimited: boolean2(),
|
|
11978
|
+
retryAfterMs: number2(),
|
|
11925
11979
|
skippedKnown: number2(),
|
|
11926
11980
|
skippedUndated: number2(),
|
|
11927
11981
|
skippedUngrounded: number2(),
|
|
11982
|
+
tapDailyBudget: number2().int(),
|
|
11983
|
+
tapDailyCallsSpent: number2().int(),
|
|
11928
11984
|
tracksSkippedArtistRule: number2().optional()
|
|
11929
11985
|
}));
|
|
11930
11986
|
LabelImagesBackfillFailedSchema = object({
|
|
@@ -12484,7 +12540,10 @@ var init_admin_projections = __esm(() => {
|
|
|
12484
12540
|
projections: object({
|
|
12485
12541
|
artistQualification: ProjectionFamilyStatusSchema,
|
|
12486
12542
|
crawlDueWork: ProjectionFamilyStatusSchema,
|
|
12487
|
-
publicAggregates: ProjectionFamilyStatusSchema.extend({
|
|
12543
|
+
publicAggregates: ProjectionFamilyStatusSchema.extend({
|
|
12544
|
+
anchorsReady: boolean2(),
|
|
12545
|
+
durationGenerationReady: boolean2()
|
|
12546
|
+
}),
|
|
12488
12547
|
trackDueWork: ProjectionFamilyStatusSchema.extend({
|
|
12489
12548
|
catalogueRankMarkerAgeMs: CountSchema.nullable().optional()
|
|
12490
12549
|
})
|
|
@@ -13581,7 +13640,7 @@ var init_admin_hub_counts = __esm(() => {
|
|
|
13581
13640
|
});
|
|
13582
13641
|
|
|
13583
13642
|
// ../../packages/contracts/src/orpc/admin-labels.ts
|
|
13584
|
-
var LabelSeedStateSchema, LabelTriageVerdictSchema, LabelAdminItemSchema, listLabelsAdmin, updateLabel, listLabelArtistRules, replaceLabelArtistRules, MergeLabelResultSchema, mergeLabel, MB_LABEL_MBID_PATTERN, MintLabelOutcomeSchema, LabelTakeOverResultSchema, mintLabel, LabelAliasSourceSchema, LabelAliasKindSchema, LabelAliasCandidateSchema, listLabelAliases, confirmLabelAlias, rejectLabelAlias, DescribeLabelBodySchema, describeLabel, draftLabelBio, LabelBioWorkItemSchema, listLabelsMissingBio, TriageRuleProposalSchema, RecordLabelTriageBodySchema, recordLabelTriage, adminLabelsContract;
|
|
13643
|
+
var LabelSeedStateSchema, LabelTriageVerdictSchema, LabelAdminItemSchema, listLabelsAdmin, updateLabel, listLabelArtistRules, LABEL_ARTIST_RULES_MAX = 100, LABEL_TRIAGE_RULE_PROPOSALS_MAX, replaceLabelArtistRules, MergeLabelResultSchema, mergeLabel, MB_LABEL_MBID_PATTERN, MintLabelOutcomeSchema, LabelTakeOverResultSchema, mintLabel, LabelAliasSourceSchema, LabelAliasKindSchema, LabelAliasCandidateSchema, listLabelAliases, confirmLabelAlias, rejectLabelAlias, DescribeLabelBodySchema, describeLabel, draftLabelBio, LabelBioWorkItemSchema, listLabelsMissingBio, TriageRuleProposalSchema, RecordLabelTriageBodySchema, recordLabelTriage, adminLabelsContract;
|
|
13585
13644
|
var init_admin_labels = __esm(() => {
|
|
13586
13645
|
init_dist3();
|
|
13587
13646
|
init_zod();
|
|
@@ -13634,6 +13693,7 @@ var init_admin_labels = __esm(() => {
|
|
|
13634
13693
|
summary: "List one label's artist rules for future catalogue acquisition",
|
|
13635
13694
|
tags: ["Admin"]
|
|
13636
13695
|
}).input(object({ id: string2() })).output(object({ ok: literal(true), rules: array(ArtistRuleSchema) }));
|
|
13696
|
+
LABEL_TRIAGE_RULE_PROPOSALS_MAX = LABEL_ARTIST_RULES_MAX * 2;
|
|
13637
13697
|
replaceLabelArtistRules = oc.route({
|
|
13638
13698
|
method: "PUT",
|
|
13639
13699
|
operationId: "replaceLabelArtistRules",
|
|
@@ -13642,7 +13702,7 @@ var init_admin_labels = __esm(() => {
|
|
|
13642
13702
|
tags: ["Admin"]
|
|
13643
13703
|
}).input(object({
|
|
13644
13704
|
id: string2(),
|
|
13645
|
-
rules: array(ArtistRuleInputSchema).max(
|
|
13705
|
+
rules: array(ArtistRuleInputSchema).max(LABEL_ARTIST_RULES_MAX).superRefine((rules, context) => {
|
|
13646
13706
|
const seen = new Set;
|
|
13647
13707
|
for (const [index, rule] of rules.entries()) {
|
|
13648
13708
|
if (seen.has(rule.artistMbid)) {
|
|
@@ -13799,7 +13859,7 @@ var init_admin_labels = __esm(() => {
|
|
|
13799
13859
|
reason: string2().optional(),
|
|
13800
13860
|
residualOffLaneShare: number2().min(0).max(1).optional(),
|
|
13801
13861
|
roundId: string2(),
|
|
13802
|
-
rules: array(TriageRuleProposalSchema).optional(),
|
|
13862
|
+
rules: array(TriageRuleProposalSchema).max(LABEL_TRIAGE_RULE_PROPOSALS_MAX).optional(),
|
|
13803
13863
|
verdict: LabelTriageVerdictSchema,
|
|
13804
13864
|
verifyAgrees: boolean2().optional(),
|
|
13805
13865
|
verifyEvidence: string2().optional()
|
|
@@ -15414,7 +15474,7 @@ var init_admin_tracks = __esm(() => {
|
|
|
15414
15474
|
debtAware: string2().optional(),
|
|
15415
15475
|
kind: TrackWorkKindSchema,
|
|
15416
15476
|
limit: number3().int().min(1).max(250).default(50),
|
|
15417
|
-
paidMode: _enum(["quota", "prior"]).optional(),
|
|
15477
|
+
paidMode: _enum(["quota", "prior", "unasked"]).optional(),
|
|
15418
15478
|
scope: TrackWorkScopeSchema.default("all")
|
|
15419
15479
|
})).output(object({
|
|
15420
15480
|
capabilities: TrackWorkCapabilitiesSchema.optional(),
|
|
@@ -15789,7 +15849,8 @@ var init_follow_digest = __esm(() => {
|
|
|
15789
15849
|
sent: number2(),
|
|
15790
15850
|
skipped: number2(),
|
|
15791
15851
|
unknown: number2(),
|
|
15792
|
-
weekKey: string2()
|
|
15852
|
+
weekKey: string2(),
|
|
15853
|
+
windowClosed: boolean2()
|
|
15793
15854
|
}));
|
|
15794
15855
|
getFollowDigestState = oc.route({
|
|
15795
15856
|
method: "GET",
|
|
@@ -19275,6 +19336,12 @@ async function requeueAnchorCommand(trackIds) {
|
|
|
19275
19336
|
async function requeueIsrcRecoveryCommand(input) {
|
|
19276
19337
|
return adminApiPost("/api/v1/admin/catalogue/isrc-recovery/requeue", input);
|
|
19277
19338
|
}
|
|
19339
|
+
async function labelReleasesBudgetCommand() {
|
|
19340
|
+
return adminApiGet("/api/v1/admin/catalogue/label-releases-budget");
|
|
19341
|
+
}
|
|
19342
|
+
async function setLabelReleasesBudgetCommand(dailyBudget) {
|
|
19343
|
+
return adminApiPut("/api/v1/admin/catalogue/label-releases-budget", { dailyBudget });
|
|
19344
|
+
}
|
|
19278
19345
|
async function anchorApifyBudgetCommand() {
|
|
19279
19346
|
return adminApiGet("/api/v1/admin/catalogue/anchor/apify-budget");
|
|
19280
19347
|
}
|
|
@@ -22715,6 +22782,8 @@ JSON field reference:
|
|
|
22715
22782
|
});
|
|
22716
22783
|
if (options.json) {
|
|
22717
22784
|
printJson(result);
|
|
22785
|
+
} else if (result.windowClosed && !result.dryRun) {
|
|
22786
|
+
console.log("Follow digest sends open Friday at 17:00 Amsterdam.");
|
|
22718
22787
|
} else {
|
|
22719
22788
|
console.log(`Considered ${result.considered}; sent ${result.sent}; empty ${result.empty}; next ${result.nextCursor ?? "done"}.`);
|
|
22720
22789
|
}
|
|
@@ -23064,6 +23133,29 @@ JSON field reference:
|
|
|
23064
23133
|
}
|
|
23065
23134
|
console.log(`Re-queued ${requeued} of ${trackIds.length} row(s) \u2014 the next anchor tick picks them up at their real priority.`);
|
|
23066
23135
|
});
|
|
23136
|
+
const labelReleasesBudget = catalogue.command("label-releases-budget").description("Read or set the label releases tap daily Spotify call budget");
|
|
23137
|
+
labelReleasesBudget.option("--json", "Print JSON", false).action(async (options) => {
|
|
23138
|
+
await Promise.resolve().then(() => init_admin_catalogue2());
|
|
23139
|
+
const state = await labelReleasesBudgetCommand();
|
|
23140
|
+
if (options.json) {
|
|
23141
|
+
printJson({ ...state, ok: true });
|
|
23142
|
+
return;
|
|
23143
|
+
}
|
|
23144
|
+
console.log(`LABEL RELEASES BUDGET \u2014 ${state.callsSpent}/${state.dailyBudget} tap calls today \xB7 ${state.spotifyDailyCalls} Spotify calls total`);
|
|
23145
|
+
});
|
|
23146
|
+
labelReleasesBudget.command("set").requiredOption("--calls <count>", "Daily tap Spotify call budget").option("--json", "Print JSON", false).action(async (options) => {
|
|
23147
|
+
await Promise.resolve().then(() => init_admin_catalogue2());
|
|
23148
|
+
const calls = Number(options.calls);
|
|
23149
|
+
if (!Number.isSafeInteger(calls) || calls < 0 || calls > 1e6) {
|
|
23150
|
+
throw new Error("--calls must be an integer from 0 to 1000000");
|
|
23151
|
+
}
|
|
23152
|
+
const state = await setLabelReleasesBudgetCommand(calls);
|
|
23153
|
+
if (options.json) {
|
|
23154
|
+
printJson({ ...state, ok: true });
|
|
23155
|
+
return;
|
|
23156
|
+
}
|
|
23157
|
+
console.log(`LABEL RELEASES BUDGET \u2014 ${state.callsSpent}/${state.dailyBudget} tap calls today \xB7 ${state.spotifyDailyCalls} Spotify calls total`);
|
|
23158
|
+
});
|
|
23067
23159
|
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) => {
|
|
23068
23160
|
await Promise.resolve().then(() => init_admin_catalogue2());
|
|
23069
23161
|
const state = await anchorBreakerCommand();
|
|
@@ -26408,6 +26500,7 @@ var stringOptions = new Set([
|
|
|
26408
26500
|
"--bpm",
|
|
26409
26501
|
"--bpm-confidence",
|
|
26410
26502
|
"--bpm-source",
|
|
26503
|
+
"--calls",
|
|
26411
26504
|
"--composition",
|
|
26412
26505
|
"--consumer-digest",
|
|
26413
26506
|
"--consumer-item-count",
|
package/package.json
CHANGED