fluncle 0.109.0 → 0.110.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 +115 -5
- package/package.json +1 -1
package/bin/fluncle.mjs
CHANGED
|
@@ -557,7 +557,7 @@ function parseVersion(version) {
|
|
|
557
557
|
var currentVersion;
|
|
558
558
|
var init_version = __esm(() => {
|
|
559
559
|
init_output();
|
|
560
|
-
currentVersion = "0.
|
|
560
|
+
currentVersion = "0.110.0".trim() ? "0.110.0".trim() : "0.1.0";
|
|
561
561
|
});
|
|
562
562
|
|
|
563
563
|
// src/update-notifier.ts
|
|
@@ -2207,7 +2207,7 @@ function parseVersion2(version) {
|
|
|
2207
2207
|
var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
|
|
2208
2208
|
var init_version2 = __esm(() => {
|
|
2209
2209
|
init_output();
|
|
2210
|
-
currentVersion2 = "0.
|
|
2210
|
+
currentVersion2 = "0.110.0".trim() ? "0.110.0".trim() : "0.1.0";
|
|
2211
2211
|
});
|
|
2212
2212
|
|
|
2213
2213
|
// ../../packages/registry/src/index.ts
|
|
@@ -2679,7 +2679,7 @@ var init_src = __esm(() => {
|
|
|
2679
2679
|
{
|
|
2680
2680
|
command: "ssh rave.fluncle.com",
|
|
2681
2681
|
exposedContent: [
|
|
2682
|
-
"the rave terminal TUI:
|
|
2682
|
+
"the rave terminal TUI: Latest bangers, Mixtape archive, Submit, Subscribe, Install CLI, About",
|
|
2683
2683
|
"deep-register one-shots: `ssh rave.fluncle.com latest|random`"
|
|
2684
2684
|
],
|
|
2685
2685
|
kind: "ssh",
|
|
@@ -2797,7 +2797,7 @@ var init_src = __esm(() => {
|
|
|
2797
2797
|
],
|
|
2798
2798
|
kind: "cron",
|
|
2799
2799
|
name: "cron.embed",
|
|
2800
|
-
operatorNotes: "every 5m. On-box MuQ (torch, ~16s/track), zero LLM tokens. Writes the vector via the agent-tier update_track. Source: docs/agents/hermes/scripts/embed-sweep.* + embed-track.py. See docs/
|
|
2800
|
+
operatorNotes: "every 5m. On-box MuQ (torch, ~16s/track), zero LLM tokens. Writes the vector via the agent-tier update_track. Source: docs/agents/hermes/scripts/embed-sweep.* + embed-track.py. See docs/track-lifecycle.md.",
|
|
2801
2801
|
probeConfig: { cadenceMs: 5 * MINUTE_MS, cronName: "fluncle-embed", kind: "cron" },
|
|
2802
2802
|
weights: { status: "hidden" }
|
|
2803
2803
|
},
|
|
@@ -2808,7 +2808,7 @@ var init_src = __esm(() => {
|
|
|
2808
2808
|
],
|
|
2809
2809
|
kind: "cron",
|
|
2810
2810
|
name: "cron.capture",
|
|
2811
|
-
operatorNotes: "every 5m, run by a rave-02 HOST systemd timer (docs/agents/hermes/capture-timer/) — NOT a gateway cron: a proxied yt-dlp fetch has an unbounded tail that would starve the 5-min enrich/context/note sweeps on the shared serial runner. A NON-BLOCKING side-channel (never gates enrich/embed). Runs yt-dlp through a residential proxy on a per-track sticky session, duration-guards the match, stores the full song in the PRIVATE fluncle-source-audio bucket (S3-direct), and writes back via the agent-tier update_track (with per-finding backoff). yt-dlp + ffprobe are a box deploy prereq. Newest-first so a fresh add jumps the backfill. Source: docs/agents/hermes/scripts/capture-sweep.*. See docs/
|
|
2811
|
+
operatorNotes: "every 5m, run by a rave-02 HOST systemd timer (docs/agents/hermes/capture-timer/) — NOT a gateway cron: a proxied yt-dlp fetch has an unbounded tail that would starve the 5-min enrich/context/note sweeps on the shared serial runner. A NON-BLOCKING side-channel (never gates enrich/embed). Runs yt-dlp through a residential proxy on a per-track sticky session, duration-guards the match, stores the full song in the PRIVATE fluncle-source-audio bucket (S3-direct), and writes back via the agent-tier update_track (with per-finding backoff). yt-dlp + ffprobe are a box deploy prereq. Newest-first so a fresh add jumps the backfill. Source: docs/agents/hermes/scripts/capture-sweep.*. See docs/track-lifecycle.md.",
|
|
2812
2812
|
probeConfig: { cadenceMs: 5 * MINUTE_MS, cronName: "fluncle-capture", kind: "cron" },
|
|
2813
2813
|
weights: { status: "hidden" }
|
|
2814
2814
|
},
|
|
@@ -5013,6 +5013,26 @@ var init_admin_artists = __esm(() => {
|
|
|
5013
5013
|
init_api();
|
|
5014
5014
|
});
|
|
5015
5015
|
|
|
5016
|
+
// src/commands/preview-migration.ts
|
|
5017
|
+
var exports_preview_migration = {};
|
|
5018
|
+
__export(exports_preview_migration, {
|
|
5019
|
+
migratePreviewArchiveCommand: () => migratePreviewArchiveCommand
|
|
5020
|
+
});
|
|
5021
|
+
async function migratePreviewArchiveCommand(args) {
|
|
5022
|
+
const params = new URLSearchParams({
|
|
5023
|
+
dryRun: String(args.dryRun),
|
|
5024
|
+
limit: String(args.limit),
|
|
5025
|
+
mode: args.mode
|
|
5026
|
+
});
|
|
5027
|
+
if (args.cursor) {
|
|
5028
|
+
params.set("cursor", args.cursor);
|
|
5029
|
+
}
|
|
5030
|
+
return adminApiPost(`/api/admin/migrations/preview-archive?${params.toString()}`);
|
|
5031
|
+
}
|
|
5032
|
+
var init_preview_migration = __esm(() => {
|
|
5033
|
+
init_api();
|
|
5034
|
+
});
|
|
5035
|
+
|
|
5016
5036
|
// src/interactive.ts
|
|
5017
5037
|
var exports_interactive = {};
|
|
5018
5038
|
__export(exports_interactive, {
|
|
@@ -7844,6 +7864,14 @@ function addAdminCommands(program2) {
|
|
|
7844
7864
|
const { resolveArtistCommand: resolveArtistCommand2 } = await Promise.resolve().then(() => (init_admin_artists(), exports_admin_artists));
|
|
7845
7865
|
await runArtistResolve(artistId, options, resolveArtistCommand2);
|
|
7846
7866
|
});
|
|
7867
|
+
const migrations = configureCommand(admin.command("migrations").description("One-off operator data migrations"));
|
|
7868
|
+
migrations.action(() => {
|
|
7869
|
+
migrations.outputHelp();
|
|
7870
|
+
});
|
|
7871
|
+
migrations.command("preview-archive").description("Move archived 30s previews from the public bucket to the private one (REF-05)").option("--execute", "Actually perform the migration (default is a dry run)", false).option("--delete-public", "Delete phase: sweep the whole public analysis/previews/ prefix (run only after a full copy)", false).option("--verify", "Read-only: count the objects still under the public analysis/previews/ prefix", false).option("--limit <limit>", "Max findings/objects to process per pass", "50").option("--json", "Print JSON", false).action(async (options) => {
|
|
7872
|
+
const { migratePreviewArchiveCommand: migratePreviewArchiveCommand2 } = await Promise.resolve().then(() => (init_preview_migration(), exports_preview_migration));
|
|
7873
|
+
await runMigratePreviewArchive(options, migratePreviewArchiveCommand2);
|
|
7874
|
+
});
|
|
7847
7875
|
}
|
|
7848
7876
|
async function runTrackPreviewArchive(idOrLogId, options, previewArchiveUploadCommand2) {
|
|
7849
7877
|
if (!idOrLogId || !options.file || !options.source || !options.mime) {
|
|
@@ -7936,6 +7964,88 @@ async function runTrackNote(idOrLogId, options, trackNoteCommand2) {
|
|
|
7936
7964
|
console.log(`Authored the note for ${result.logId}:`);
|
|
7937
7965
|
console.log(` ${result.note}`);
|
|
7938
7966
|
}
|
|
7967
|
+
async function runMigratePreviewArchive(options, migratePreviewArchiveCommand2) {
|
|
7968
|
+
const limit = options.limit === undefined ? 50 : Number.parseInt(options.limit, 10);
|
|
7969
|
+
if (!Number.isInteger(limit) || limit < 1) {
|
|
7970
|
+
throw new Error("Limit must be a positive integer");
|
|
7971
|
+
}
|
|
7972
|
+
const mode = options.verify ? "verify" : options.deletePublic ? "delete" : "copy";
|
|
7973
|
+
const dryRun = mode === "verify" ? true : !options.execute;
|
|
7974
|
+
if (mode === "verify") {
|
|
7975
|
+
const result = await migratePreviewArchiveCommand2({ dryRun: true, limit, mode });
|
|
7976
|
+
if (options.json) {
|
|
7977
|
+
printJson({ mode, ok: true, remaining: result.remaining, sampleKeys: result.sampleKeys });
|
|
7978
|
+
return;
|
|
7979
|
+
}
|
|
7980
|
+
console.log(`${result.remaining} object(s) remain under the public analysis/previews/ prefix.`);
|
|
7981
|
+
for (const key of result.sampleKeys) {
|
|
7982
|
+
console.log(` ${key}`);
|
|
7983
|
+
}
|
|
7984
|
+
return;
|
|
7985
|
+
}
|
|
7986
|
+
const copied = [];
|
|
7987
|
+
const deleted = [];
|
|
7988
|
+
const skipped = [];
|
|
7989
|
+
const failed = [];
|
|
7990
|
+
let cursor;
|
|
7991
|
+
let remaining = 0;
|
|
7992
|
+
let blocked = null;
|
|
7993
|
+
for (;; ) {
|
|
7994
|
+
const result = await migratePreviewArchiveCommand2({ cursor, dryRun, limit, mode });
|
|
7995
|
+
if (result.blocked) {
|
|
7996
|
+
blocked = result.blocked;
|
|
7997
|
+
remaining = result.remaining;
|
|
7998
|
+
break;
|
|
7999
|
+
}
|
|
8000
|
+
copied.push(...result.copied);
|
|
8001
|
+
deleted.push(...result.deleted);
|
|
8002
|
+
skipped.push(...result.skipped);
|
|
8003
|
+
failed.push(...result.failed);
|
|
8004
|
+
remaining = result.remaining;
|
|
8005
|
+
if (!options.json) {
|
|
8006
|
+
const verb = dryRun ? "would" : "did";
|
|
8007
|
+
console.log(` \u2026${mode} pass (${verb}): +${result.copiedCount} copied, +${result.deletedCount} deleted, ${result.skippedCount} skipped, ${result.failedCount} failed; ${result.remaining} remaining`);
|
|
8008
|
+
}
|
|
8009
|
+
if (result.nextCursor === null) {
|
|
8010
|
+
break;
|
|
8011
|
+
}
|
|
8012
|
+
cursor = result.nextCursor;
|
|
8013
|
+
}
|
|
8014
|
+
if (options.json) {
|
|
8015
|
+
printJson({
|
|
8016
|
+
blocked,
|
|
8017
|
+
copied,
|
|
8018
|
+
copiedCount: copied.length,
|
|
8019
|
+
deleted,
|
|
8020
|
+
deletedCount: deleted.length,
|
|
8021
|
+
dryRun,
|
|
8022
|
+
failed,
|
|
8023
|
+
failedCount: failed.length,
|
|
8024
|
+
mode,
|
|
8025
|
+
ok: true,
|
|
8026
|
+
remaining,
|
|
8027
|
+
skipped,
|
|
8028
|
+
skippedCount: skipped.length
|
|
8029
|
+
});
|
|
8030
|
+
return;
|
|
8031
|
+
}
|
|
8032
|
+
if (blocked) {
|
|
8033
|
+
console.log(`REFUSED (${blocked}): ${remaining} legacy row(s) still need copying first.`);
|
|
8034
|
+
return;
|
|
8035
|
+
}
|
|
8036
|
+
const done = mode === "delete" ? deleted.length : copied.length;
|
|
8037
|
+
const noun = mode === "delete" ? "public object(s) deleted" : "preview(s) copied to the private bucket";
|
|
8038
|
+
const prefix = dryRun ? "DRY RUN \u2014 would have: " : "";
|
|
8039
|
+
console.log(`${prefix}${done} ${noun}; ${skipped.length} skipped; ${failed.length} failed; ${remaining} still under the prefix.`);
|
|
8040
|
+
for (const item of skipped) {
|
|
8041
|
+
if (item.reason === "private_copy_absent") {
|
|
8042
|
+
console.log(` LEFT (no private copy) ${item.trackId}`);
|
|
8043
|
+
}
|
|
8044
|
+
}
|
|
8045
|
+
for (const item of failed) {
|
|
8046
|
+
console.log(` FAILED ${item.trackId}: ${item.error}`);
|
|
8047
|
+
}
|
|
8048
|
+
}
|
|
7939
8049
|
async function runPreviewArchiveBackfill(options, previewArchiveBackfillCommand2) {
|
|
7940
8050
|
const limit = options.limit === undefined ? undefined : Number.parseInt(options.limit, 10);
|
|
7941
8051
|
if (limit !== undefined && (!Number.isInteger(limit) || limit < 1)) {
|
package/package.json
CHANGED