fluncle 0.97.0 → 0.98.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 +72 -3
- 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.98.0".trim() ? "0.98.0".trim() : "0.1.0";
|
|
561
561
|
});
|
|
562
562
|
|
|
563
563
|
// src/update-notifier.ts
|
|
@@ -2187,7 +2187,7 @@ function parseVersion2(version) {
|
|
|
2187
2187
|
var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
|
|
2188
2188
|
var init_version2 = __esm(() => {
|
|
2189
2189
|
init_output();
|
|
2190
|
-
currentVersion2 = "0.
|
|
2190
|
+
currentVersion2 = "0.98.0".trim() ? "0.98.0".trim() : "0.1.0";
|
|
2191
2191
|
});
|
|
2192
2192
|
|
|
2193
2193
|
// ../../packages/registry/src/index.ts
|
|
@@ -2737,6 +2737,17 @@ var init_src = __esm(() => {
|
|
|
2737
2737
|
probeConfig: { cadenceMs: 5 * MINUTE_MS, cronName: "fluncle-enrich", kind: "cron" },
|
|
2738
2738
|
weights: { status: "hidden" }
|
|
2739
2739
|
},
|
|
2740
|
+
{
|
|
2741
|
+
command: "fluncle admin tracks embed --queue",
|
|
2742
|
+
exposedContent: [
|
|
2743
|
+
"MuQ-large audio embedding (1024-d) for sonic similarity + clusters (--no-agent, on-box torch)"
|
|
2744
|
+
],
|
|
2745
|
+
kind: "cron",
|
|
2746
|
+
name: "cron.embed",
|
|
2747
|
+
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/audio-embedding-rfc.md.",
|
|
2748
|
+
probeConfig: { cadenceMs: 5 * MINUTE_MS, cronName: "fluncle-embed", kind: "cron" },
|
|
2749
|
+
weights: { status: "hidden" }
|
|
2750
|
+
},
|
|
2740
2751
|
{
|
|
2741
2752
|
command: "fluncle admin tracks context --queue",
|
|
2742
2753
|
exposedContent: [
|
|
@@ -3079,6 +3090,9 @@ async function trackUpdateCommand(trackId, options) {
|
|
|
3079
3090
|
if (options.features !== undefined) {
|
|
3080
3091
|
body.features = options.features;
|
|
3081
3092
|
}
|
|
3093
|
+
if (options.embedding !== undefined) {
|
|
3094
|
+
body.embedding = options.embedding;
|
|
3095
|
+
}
|
|
3082
3096
|
if (options.note !== undefined) {
|
|
3083
3097
|
body.note = options.note;
|
|
3084
3098
|
}
|
|
@@ -3441,6 +3455,7 @@ __export(exports_admin_tracks, {
|
|
|
3441
3455
|
noteQueueCommand: () => noteQueueCommand,
|
|
3442
3456
|
listCommand: () => listCommand,
|
|
3443
3457
|
enrichQueueCommand: () => enrichQueueCommand,
|
|
3458
|
+
embedQueueCommand: () => embedQueueCommand,
|
|
3444
3459
|
contextQueueCommand: () => contextQueueCommand,
|
|
3445
3460
|
backfillLastfmCommand: () => backfillLastfmCommand,
|
|
3446
3461
|
backfillDiscogsCommand: () => backfillDiscogsCommand
|
|
@@ -3448,6 +3463,7 @@ __export(exports_admin_tracks, {
|
|
|
3448
3463
|
async function fetchAdminTracks(options) {
|
|
3449
3464
|
const {
|
|
3450
3465
|
hasContext,
|
|
3466
|
+
hasEmbedding,
|
|
3451
3467
|
hasKey,
|
|
3452
3468
|
hasNote,
|
|
3453
3469
|
hasObservation,
|
|
@@ -3467,6 +3483,9 @@ async function fetchAdminTracks(options) {
|
|
|
3467
3483
|
if (hasKey !== undefined) {
|
|
3468
3484
|
params.set("hasKey", String(hasKey));
|
|
3469
3485
|
}
|
|
3486
|
+
if (hasEmbedding !== undefined) {
|
|
3487
|
+
params.set("hasEmbedding", String(hasEmbedding));
|
|
3488
|
+
}
|
|
3470
3489
|
if (hasContext !== undefined) {
|
|
3471
3490
|
params.set("hasContext", String(hasContext));
|
|
3472
3491
|
}
|
|
@@ -3519,6 +3538,9 @@ async function queueCommand(limit, filters = {}) {
|
|
|
3519
3538
|
async function enrichQueueCommand(limit) {
|
|
3520
3539
|
return fetchAdminTracks({ max: limit, order: "asc", status: "queue" });
|
|
3521
3540
|
}
|
|
3541
|
+
async function embedQueueCommand(limit) {
|
|
3542
|
+
return fetchAdminTracks({ hasEmbedding: false, max: limit, order: "asc" });
|
|
3543
|
+
}
|
|
3522
3544
|
async function contextQueueCommand(limit, retryEmptyContext = false) {
|
|
3523
3545
|
return fetchAdminTracks({ hasContext: false, max: limit, order: "asc", retryEmptyContext });
|
|
3524
3546
|
}
|
|
@@ -7641,6 +7663,15 @@ function addAdminCommands(program2) {
|
|
|
7641
7663
|
const { enrichQueueCommand: enrichQueueCommand2 } = await Promise.resolve().then(() => (init_admin_tracks(), exports_admin_tracks));
|
|
7642
7664
|
await runAdminEnrichQueue(options, enrichQueueCommand2);
|
|
7643
7665
|
});
|
|
7666
|
+
adminTracks.command("embed").description("Audio-embedding worklist (findings with no MuQ vector yet) \u2014 use --queue").option("--queue", "Show the embedding worklist, oldest first", false).option("--limit <limit>", "Number of findings to show with --queue", "10").option("--json", "Print JSON", false).action(async (options) => {
|
|
7667
|
+
if (!options.queue) {
|
|
7668
|
+
console.error("`tracks embed` is a worklist view \u2014 embedding runs on the on-box `fluncle-embed` cron.\nUse `tracks embed --queue` to see findings needing an audio embedding.");
|
|
7669
|
+
process.exitCode = 1;
|
|
7670
|
+
return;
|
|
7671
|
+
}
|
|
7672
|
+
const { embedQueueCommand: embedQueueCommand2 } = await Promise.resolve().then(() => (init_admin_tracks(), exports_admin_tracks));
|
|
7673
|
+
await runAdminEmbedQueue(options, embedQueueCommand2);
|
|
7674
|
+
});
|
|
7644
7675
|
adminTracks.command("vehicles").description("Recent video vehicles, newest first (the style ledger for diversity)").option("--limit <limit>", "Number of vehicles to show", "10").option("--json", "Print JSON", false).action(async (options) => {
|
|
7645
7676
|
const { vehiclesCommand: vehiclesCommand2 } = await Promise.resolve().then(() => (init_admin_tracks(), exports_admin_tracks));
|
|
7646
7677
|
await runAdminVehicles(options, vehiclesCommand2);
|
|
@@ -7650,7 +7681,7 @@ function addAdminCommands(program2) {
|
|
|
7650
7681
|
const { trackGetAdminCommand: trackGetAdminCommand2 } = await Promise.resolve().then(() => (init_track(), exports_track));
|
|
7651
7682
|
await runTrackGetAdmin(idOrLogId, options, trackGetAdminCommand2);
|
|
7652
7683
|
});
|
|
7653
|
-
adminTrack.command("update").description("Certify a track into the archive").argument("[trackId]").option("--bpm <number>", "Track BPM").option("--features <json>", "Audio feature JSON").option("--json", "Print JSON", false).option("--key <key>", "Musical key").option("--note <text>", "Operator note").option("--status <status>", "Enrichment status").option("--video-url <url>", "Rendered video URL").allowExcessArguments().action(async (trackId, options) => {
|
|
7684
|
+
adminTrack.command("update").description("Certify a track into the archive").argument("[trackId]").option("--bpm <number>", "Track BPM").option("--embedding <json>", "MuQ audio embedding as a JSON array of 1024 floats").option("--embedding-file <file>", "Read the MuQ embedding JSON array from a file").option("--features <json>", "Audio feature JSON").option("--json", "Print JSON", false).option("--key <key>", "Musical key").option("--note <text>", "Operator note").option("--status <status>", "Enrichment status").option("--video-url <url>", "Rendered video URL").allowExcessArguments().action(async (trackId, options) => {
|
|
7654
7685
|
const { trackUpdateCommand: trackUpdateCommand2 } = await Promise.resolve().then(() => (init_track(), exports_track));
|
|
7655
7686
|
await runTrackUpdate(trackId, options, trackUpdateCommand2);
|
|
7656
7687
|
});
|
|
@@ -8260,6 +8291,21 @@ async function runTrackGetAdmin(idOrLogId, options, trackGetAdminCommand2) {
|
|
|
8260
8291
|
console.log(`Log: ${t.logPageUrl}`);
|
|
8261
8292
|
}
|
|
8262
8293
|
}
|
|
8294
|
+
function parseEmbeddingArg(raw) {
|
|
8295
|
+
if (raw === undefined) {
|
|
8296
|
+
return;
|
|
8297
|
+
}
|
|
8298
|
+
let parsed;
|
|
8299
|
+
try {
|
|
8300
|
+
parsed = JSON.parse(raw);
|
|
8301
|
+
} catch {
|
|
8302
|
+
throw new Error("Invalid --embedding: expected a JSON array of 1024 floats");
|
|
8303
|
+
}
|
|
8304
|
+
if (!Array.isArray(parsed) || parsed.some((value) => typeof value !== "number" || !Number.isFinite(value))) {
|
|
8305
|
+
throw new Error("Invalid --embedding: expected a JSON array of 1024 finite numbers");
|
|
8306
|
+
}
|
|
8307
|
+
return parsed;
|
|
8308
|
+
}
|
|
8263
8309
|
async function runTrackUpdate(trackId, options, trackUpdateCommand2) {
|
|
8264
8310
|
if (!trackId) {
|
|
8265
8311
|
throw new Error("Missing track id. Usage: fluncle admin tracks update <track_id>");
|
|
@@ -8268,8 +8314,11 @@ async function runTrackUpdate(trackId, options, trackUpdateCommand2) {
|
|
|
8268
8314
|
if (bpm !== undefined && !Number.isFinite(bpm)) {
|
|
8269
8315
|
throw new Error(`Invalid --bpm: ${options.bpm}`);
|
|
8270
8316
|
}
|
|
8317
|
+
const embeddingRaw = options.embeddingFile ? readFileSync6(options.embeddingFile, "utf8") : options.embedding;
|
|
8318
|
+
const embedding = parseEmbeddingArg(embeddingRaw);
|
|
8271
8319
|
const result = await trackUpdateCommand2(trackId, {
|
|
8272
8320
|
bpm,
|
|
8321
|
+
embedding,
|
|
8273
8322
|
features: options.features,
|
|
8274
8323
|
key: options.key,
|
|
8275
8324
|
note: options.note,
|
|
@@ -8732,6 +8781,26 @@ async function runAdminEnrichQueue(options, enrichQueueCommand2) {
|
|
|
8732
8781
|
console.log(trackRows2(tracks).join(`
|
|
8733
8782
|
`));
|
|
8734
8783
|
}
|
|
8784
|
+
async function runAdminEmbedQueue(options, embedQueueCommand2) {
|
|
8785
|
+
const limit = parseListLimit(options.limit);
|
|
8786
|
+
const tracks = await embedQueueCommand2(limit);
|
|
8787
|
+
if (options.json) {
|
|
8788
|
+
printJson({
|
|
8789
|
+
ok: true,
|
|
8790
|
+
tracks
|
|
8791
|
+
});
|
|
8792
|
+
return;
|
|
8793
|
+
}
|
|
8794
|
+
if (tracks.length === 0) {
|
|
8795
|
+
console.log("Nothing awaiting an embedding. Every finding is embedded.");
|
|
8796
|
+
return;
|
|
8797
|
+
}
|
|
8798
|
+
const { trackRows: trackRows2 } = await Promise.resolve().then(() => (init_format2(), exports_format));
|
|
8799
|
+
const noun = tracks.length === 1 ? "finding" : "findings";
|
|
8800
|
+
console.log(`${tracks.length} ${noun} needing an audio embedding, oldest first:`);
|
|
8801
|
+
console.log(trackRows2(tracks).join(`
|
|
8802
|
+
`));
|
|
8803
|
+
}
|
|
8735
8804
|
async function runAdminVehicles(options, vehiclesCommand2) {
|
|
8736
8805
|
const limit = parseListLimit(options.limit);
|
|
8737
8806
|
const vehicles = await vehiclesCommand2(limit);
|
package/package.json
CHANGED