fluncle 0.259.0 → 0.261.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 +40 -16
- 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.261.0".trim() ? "0.261.0".trim() : "0.1.0";
|
|
626
626
|
});
|
|
627
627
|
|
|
628
628
|
// src/update-notifier.ts
|
|
@@ -2258,7 +2258,7 @@ var init_about = __esm(() => {
|
|
|
2258
2258
|
heading: "For the nerds",
|
|
2259
2259
|
links: [
|
|
2260
2260
|
{ label: "The Galaxy (game)", url: "https://galaxy.fluncle.com" },
|
|
2261
|
-
{ label: "SSH (
|
|
2261
|
+
{ label: "SSH (the rave terminal)", url: "ssh rave.fluncle.com" },
|
|
2262
2262
|
{ label: "Source", url: "https://github.com/mauricekleine/fluncle" }
|
|
2263
2263
|
]
|
|
2264
2264
|
}
|
|
@@ -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.261.0".trim() ? "0.261.0".trim() : "0.1.0";
|
|
2339
2339
|
});
|
|
2340
2340
|
|
|
2341
2341
|
// ../../packages/registry/src/index.ts
|
|
@@ -3293,7 +3293,7 @@ var init_src = __esm(() => {
|
|
|
3293
3293
|
},
|
|
3294
3294
|
{
|
|
3295
3295
|
command: "fluncle random",
|
|
3296
|
-
exposedContent: ["the archive throws
|
|
3296
|
+
exposedContent: ["the archive throws a banger back"],
|
|
3297
3297
|
kind: "cli",
|
|
3298
3298
|
name: "cli.random",
|
|
3299
3299
|
weights: { cli: "secondary" }
|
|
@@ -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: "
|
|
3462
|
+
operatorNotes: "daily at 07:20 Amsterdam, 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: "07:20", tz: "Europe/Amsterdam" }
|
|
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, 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",
|
|
@@ -10841,6 +10858,7 @@ var init_admin_catalogue = __esm(() => {
|
|
|
10841
10858
|
get_anchor_apify_budget: getAnchorApifyBudget,
|
|
10842
10859
|
get_capture_budget: getCaptureBudget,
|
|
10843
10860
|
get_crawl_status: getCrawlStatus,
|
|
10861
|
+
get_pipeline: getPipeline,
|
|
10844
10862
|
get_spotify_anchor_breaker: getSpotifyAnchorBreaker,
|
|
10845
10863
|
list_catalogue_tracks: listCatalogueTracks,
|
|
10846
10864
|
list_unverified_captures: listUnverifiedCaptures,
|
|
@@ -12484,7 +12502,10 @@ var init_admin_projections = __esm(() => {
|
|
|
12484
12502
|
projections: object({
|
|
12485
12503
|
artistQualification: ProjectionFamilyStatusSchema,
|
|
12486
12504
|
crawlDueWork: ProjectionFamilyStatusSchema,
|
|
12487
|
-
publicAggregates: ProjectionFamilyStatusSchema.extend({
|
|
12505
|
+
publicAggregates: ProjectionFamilyStatusSchema.extend({
|
|
12506
|
+
anchorsReady: boolean2(),
|
|
12507
|
+
durationGenerationReady: boolean2()
|
|
12508
|
+
}),
|
|
12488
12509
|
trackDueWork: ProjectionFamilyStatusSchema.extend({
|
|
12489
12510
|
catalogueRankMarkerAgeMs: CountSchema.nullable().optional()
|
|
12490
12511
|
})
|
|
@@ -15789,7 +15810,8 @@ var init_follow_digest = __esm(() => {
|
|
|
15789
15810
|
sent: number2(),
|
|
15790
15811
|
skipped: number2(),
|
|
15791
15812
|
unknown: number2(),
|
|
15792
|
-
weekKey: string2()
|
|
15813
|
+
weekKey: string2(),
|
|
15814
|
+
windowClosed: boolean2()
|
|
15793
15815
|
}));
|
|
15794
15816
|
getFollowDigestState = oc.route({
|
|
15795
15817
|
method: "GET",
|
|
@@ -22056,7 +22078,7 @@ function artistRuleLines(rules) {
|
|
|
22056
22078
|
}
|
|
22057
22079
|
function createProgram() {
|
|
22058
22080
|
const program = configureCommand(new Command);
|
|
22059
|
-
program.name("fluncle").description(fluncleTagline
|
|
22081
|
+
program.name("fluncle").description(fluncleTagline).option("--env <local|production>", "Config profile to load (default: production)").showSuggestionAfterError(false).addHelpCommand("help [command]", "Display help for command").hook("preAction", (_thisCommand, actionCommand) => {
|
|
22060
22082
|
const options = actionCommand.optsWithGlobals();
|
|
22061
22083
|
setEnvProfile(options.env);
|
|
22062
22084
|
}).addHelpText("before", `
|
|
@@ -22097,7 +22119,7 @@ async function main(args = process.argv.slice(2)) {
|
|
|
22097
22119
|
await notifyIfUpdateAvailable(args);
|
|
22098
22120
|
}
|
|
22099
22121
|
function configureCommand(command) {
|
|
22100
|
-
return command.exitOverride().addHelpCommand(false).configureOutput({
|
|
22122
|
+
return command.exitOverride().helpOption("-h, --help", "Display help for command").addHelpCommand(false).configureOutput({
|
|
22101
22123
|
writeErr: () => {}
|
|
22102
22124
|
});
|
|
22103
22125
|
}
|
|
@@ -22146,7 +22168,7 @@ function addListenCommands(program) {
|
|
|
22146
22168
|
const openCommands = await Promise.resolve().then(() => (init_open(), exports_open));
|
|
22147
22169
|
await runOpen(target, [], options, openCommands);
|
|
22148
22170
|
});
|
|
22149
|
-
program.command("random").description("The archive throws
|
|
22171
|
+
program.command("random").description("The archive throws a banger back").option("--json", "Print JSON", false).action(async (options) => {
|
|
22150
22172
|
await Promise.resolve().then(() => init_random());
|
|
22151
22173
|
await runRandom(options, randomCommand);
|
|
22152
22174
|
});
|
|
@@ -22208,7 +22230,7 @@ function addAdminCommands(program) {
|
|
|
22208
22230
|
admin.action(() => {
|
|
22209
22231
|
admin.outputHelp();
|
|
22210
22232
|
});
|
|
22211
|
-
admin.command("help", { hidden: true }).description("
|
|
22233
|
+
admin.command("help", { hidden: true }).description("Display help for command").action(() => {
|
|
22212
22234
|
admin.outputHelp();
|
|
22213
22235
|
});
|
|
22214
22236
|
admin.command("queue").description("The attention queue: what's waiting, and the day's dispatch").option("--json", "Print JSON", false).action(async (options) => {
|
|
@@ -22715,6 +22737,8 @@ JSON field reference:
|
|
|
22715
22737
|
});
|
|
22716
22738
|
if (options.json) {
|
|
22717
22739
|
printJson(result);
|
|
22740
|
+
} else if (result.windowClosed && !result.dryRun) {
|
|
22741
|
+
console.log("Follow digest sends open Friday at 17:00 Amsterdam.");
|
|
22718
22742
|
} else {
|
|
22719
22743
|
console.log(`Considered ${result.considered}; sent ${result.sent}; empty ${result.empty}; next ${result.nextCursor ?? "done"}.`);
|
|
22720
22744
|
}
|
|
@@ -26521,7 +26545,7 @@ Listen:
|
|
|
26521
26545
|
fluncle open [--limit 20] [--browser|--app] Pick a track, open it in Spotify
|
|
26522
26546
|
fluncle open playlist [--browser|--app] Open Fluncle's Findings in Spotify
|
|
26523
26547
|
fluncle open telegram [--browser|--app] Open the Telegram feed
|
|
26524
|
-
fluncle random [--json] The archive throws
|
|
26548
|
+
fluncle random [--json] The archive throws a banger back
|
|
26525
26549
|
fluncle subscribe [email] Fresh bangers, every Friday
|
|
26526
26550
|
|
|
26527
26551
|
Browse:
|
package/package.json
CHANGED