fluncle 0.153.0 → 0.155.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 +195 -3
- package/package.json +1 -1
package/bin/fluncle.mjs
CHANGED
|
@@ -561,7 +561,7 @@ function parseVersion(version) {
|
|
|
561
561
|
var currentVersion;
|
|
562
562
|
var init_version = __esm(() => {
|
|
563
563
|
init_output();
|
|
564
|
-
currentVersion = "0.
|
|
564
|
+
currentVersion = "0.155.0".trim() ? "0.155.0".trim() : "0.1.0";
|
|
565
565
|
});
|
|
566
566
|
|
|
567
567
|
// src/update-notifier.ts
|
|
@@ -2189,7 +2189,7 @@ function parseVersion2(version) {
|
|
|
2189
2189
|
var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
|
|
2190
2190
|
var init_version2 = __esm(() => {
|
|
2191
2191
|
init_output();
|
|
2192
|
-
currentVersion2 = "0.
|
|
2192
|
+
currentVersion2 = "0.155.0".trim() ? "0.155.0".trim() : "0.1.0";
|
|
2193
2193
|
});
|
|
2194
2194
|
|
|
2195
2195
|
// ../../packages/registry/src/index.ts
|
|
@@ -3626,6 +3626,7 @@ var init_admin_attention = __esm(() => {
|
|
|
3626
3626
|
"label-review": "label",
|
|
3627
3627
|
newsletter: "newsletter",
|
|
3628
3628
|
"note-rejected": "held note",
|
|
3629
|
+
"observation-rejected": "held observation",
|
|
3629
3630
|
"post-tiktok": "tiktok",
|
|
3630
3631
|
"post-youtube": "youtube",
|
|
3631
3632
|
submission: "submission",
|
|
@@ -5761,6 +5762,35 @@ var init_admin_notes = __esm(() => {
|
|
|
5761
5762
|
init_api();
|
|
5762
5763
|
});
|
|
5763
5764
|
|
|
5765
|
+
// src/commands/admin-observations.ts
|
|
5766
|
+
var exports_admin_observations = {};
|
|
5767
|
+
__export(exports_admin_observations, {
|
|
5768
|
+
observationHeldCommand: () => observationHeldCommand,
|
|
5769
|
+
observationGateCommand: () => observationGateCommand
|
|
5770
|
+
});
|
|
5771
|
+
async function observationHeldCommand(options) {
|
|
5772
|
+
const query = options.settled ? "?open=false" : "";
|
|
5773
|
+
return adminApiGet(`/api/admin/observation-rejections${query}`);
|
|
5774
|
+
}
|
|
5775
|
+
async function observationGateCommand(options) {
|
|
5776
|
+
const patch = {};
|
|
5777
|
+
if (options.minPhraseWords !== undefined) {
|
|
5778
|
+
patch.minPhraseWords = options.minPhraseWords;
|
|
5779
|
+
}
|
|
5780
|
+
if (options.maxOverlap !== undefined) {
|
|
5781
|
+
patch.maxOverlap = options.maxOverlap;
|
|
5782
|
+
}
|
|
5783
|
+
if (Object.keys(patch).length === 0) {
|
|
5784
|
+
const response2 = await adminApiGet("/api/admin/observation-rejections");
|
|
5785
|
+
return response2.gate;
|
|
5786
|
+
}
|
|
5787
|
+
const response = await adminApiPatch("/api/admin/observation-gate", patch);
|
|
5788
|
+
return response.gate;
|
|
5789
|
+
}
|
|
5790
|
+
var init_admin_observations = __esm(() => {
|
|
5791
|
+
init_api();
|
|
5792
|
+
});
|
|
5793
|
+
|
|
5764
5794
|
// src/commands/admin-catalogue.ts
|
|
5765
5795
|
var exports_admin_catalogue = {};
|
|
5766
5796
|
__export(exports_admin_catalogue, {
|
|
@@ -5866,9 +5896,29 @@ var exports_admin_artists = {};
|
|
|
5866
5896
|
__export(exports_admin_artists, {
|
|
5867
5897
|
resolveArtistCommand: () => resolveArtistCommand,
|
|
5868
5898
|
listArtistsCommand: () => listArtistsCommand,
|
|
5899
|
+
describeArtistCommand: () => describeArtistCommand,
|
|
5900
|
+
buildBioBody: () => buildBioBody,
|
|
5869
5901
|
backfillArtistsCommand: () => backfillArtistsCommand,
|
|
5870
|
-
backfillArtistImagesCommand: () => backfillArtistImagesCommand
|
|
5902
|
+
backfillArtistImagesCommand: () => backfillArtistImagesCommand,
|
|
5903
|
+
artistsBioQueueCommand: () => artistsBioQueueCommand
|
|
5871
5904
|
});
|
|
5905
|
+
function buildBioBody(options) {
|
|
5906
|
+
const body = { bio: options.bio };
|
|
5907
|
+
if (options.dryRun) {
|
|
5908
|
+
body.dryRun = true;
|
|
5909
|
+
}
|
|
5910
|
+
if (typeof options.promptVersion === "number") {
|
|
5911
|
+
body.promptVersion = options.promptVersion;
|
|
5912
|
+
}
|
|
5913
|
+
return body;
|
|
5914
|
+
}
|
|
5915
|
+
async function describeArtistCommand(slug, options) {
|
|
5916
|
+
return adminApiPost(`/api/admin/artists/${encodeURIComponent(slug)}/bio`, buildBioBody(options));
|
|
5917
|
+
}
|
|
5918
|
+
async function artistsBioQueueCommand(limit) {
|
|
5919
|
+
const response = await adminApiGet(`/api/admin/artists/bio-queue?limit=${limit}`);
|
|
5920
|
+
return response.artists;
|
|
5921
|
+
}
|
|
5872
5922
|
async function listArtistsCommand(limit, cursor) {
|
|
5873
5923
|
const params = new URLSearchParams({ limit: String(limit) });
|
|
5874
5924
|
if (cursor) {
|
|
@@ -5897,11 +5947,35 @@ var init_admin_artists = __esm(() => {
|
|
|
5897
5947
|
init_api();
|
|
5898
5948
|
});
|
|
5899
5949
|
|
|
5950
|
+
// src/commands/admin-artists.ts
|
|
5951
|
+
function buildBioBody2(options) {
|
|
5952
|
+
const body = { bio: options.bio };
|
|
5953
|
+
if (options.dryRun) {
|
|
5954
|
+
body.dryRun = true;
|
|
5955
|
+
}
|
|
5956
|
+
if (typeof options.promptVersion === "number") {
|
|
5957
|
+
body.promptVersion = options.promptVersion;
|
|
5958
|
+
}
|
|
5959
|
+
return body;
|
|
5960
|
+
}
|
|
5961
|
+
var init_admin_artists2 = __esm(() => {
|
|
5962
|
+
init_api();
|
|
5963
|
+
});
|
|
5964
|
+
|
|
5900
5965
|
// src/commands/admin-labels.ts
|
|
5901
5966
|
var exports_admin_labels = {};
|
|
5902
5967
|
__export(exports_admin_labels, {
|
|
5968
|
+
labelsBioQueueCommand: () => labelsBioQueueCommand,
|
|
5969
|
+
describeLabelCommand: () => describeLabelCommand,
|
|
5903
5970
|
backfillLabelImagesCommand: () => backfillLabelImagesCommand
|
|
5904
5971
|
});
|
|
5972
|
+
async function describeLabelCommand(slug, options) {
|
|
5973
|
+
return adminApiPost(`/api/admin/labels/${encodeURIComponent(slug)}/bio`, buildBioBody2(options));
|
|
5974
|
+
}
|
|
5975
|
+
async function labelsBioQueueCommand(limit) {
|
|
5976
|
+
const response = await adminApiGet(`/api/admin/labels/bio-queue?limit=${limit}`);
|
|
5977
|
+
return response.labels;
|
|
5978
|
+
}
|
|
5905
5979
|
async function backfillLabelImagesCommand(limit, dryRun, cursor) {
|
|
5906
5980
|
const params = new URLSearchParams({ dryRun: String(dryRun), limit: String(limit) });
|
|
5907
5981
|
if (cursor) {
|
|
@@ -5911,6 +5985,7 @@ async function backfillLabelImagesCommand(limit, dryRun, cursor) {
|
|
|
5911
5985
|
}
|
|
5912
5986
|
var init_admin_labels = __esm(() => {
|
|
5913
5987
|
init_api();
|
|
5988
|
+
init_admin_artists2();
|
|
5914
5989
|
});
|
|
5915
5990
|
|
|
5916
5991
|
// src/commands/admin-covers.ts
|
|
@@ -8901,6 +8976,18 @@ function addAdminCommands(program2) {
|
|
|
8901
8976
|
const { noteGateCommand: noteGateCommand2 } = await Promise.resolve().then(() => (init_admin_notes(), exports_admin_notes));
|
|
8902
8977
|
await runNoteGate(options, noteGateCommand2);
|
|
8903
8978
|
});
|
|
8979
|
+
const observations = configureCommand(admin.command("observations").description("The observation echo gate: held scripts + dials"));
|
|
8980
|
+
observations.action(() => {
|
|
8981
|
+
observations.outputHelp();
|
|
8982
|
+
});
|
|
8983
|
+
observations.command("held").description("The observation scripts the echo gate held back (and why)").option("--settled", "Read the ones already ruled on instead (the retune evidence)", false).option("--json", "Print JSON", false).action(async (options) => {
|
|
8984
|
+
const { observationHeldCommand: observationHeldCommand2 } = await Promise.resolve().then(() => (init_admin_observations(), exports_admin_observations));
|
|
8985
|
+
await runObservationHeld(options, observationHeldCommand2);
|
|
8986
|
+
});
|
|
8987
|
+
observations.command("gate").description("Read or retune the observation echo gate's thresholds (a flip, not a deploy)").option("--min-phrase-words <n>", "A shared run this long is a lift (2-20; default 4)").option("--max-overlap <x>", "Content-word overlap at/above this is an echo (0.05-1; default 0.3)").option("--json", "Print JSON", false).action(async (options) => {
|
|
8988
|
+
const { observationGateCommand: observationGateCommand2 } = await Promise.resolve().then(() => (init_admin_observations(), exports_admin_observations));
|
|
8989
|
+
await runObservationGate(options, observationGateCommand2);
|
|
8990
|
+
});
|
|
8904
8991
|
const catalogue = configureCommand(admin.command("catalogue").description("The catalogue (uncertified tracks): the crawler + its ranking"));
|
|
8905
8992
|
catalogue.action(() => {
|
|
8906
8993
|
catalogue.outputHelp();
|
|
@@ -9079,6 +9166,28 @@ function addAdminCommands(program2) {
|
|
|
9079
9166
|
const { resolveArtistCommand: resolveArtistCommand2 } = await Promise.resolve().then(() => (init_admin_artists(), exports_admin_artists));
|
|
9080
9167
|
await runArtistResolve(artistId, options, resolveArtistCommand2);
|
|
9081
9168
|
});
|
|
9169
|
+
artists.command("describe").description("Author the voiced bio for an artist (fills an empty bio only)").argument("[slug]").option("--queue", "Show the bio worklist (artists with findings but no bio), oldest first", false).option("--limit <limit>", "Number of artists to show with --queue", "50").option("--bio <text>", "The voice-gated bio paragraph").option("--bio-file <file>", "Read the bio from a file").option("--prompt-version <n>", "The prompt-registry version that authored the bio (the sweep sends this; it is the bio's provenance)").option("--dry-run", "Run the voice gate and report the verdict without storing anything", false).option("--json", "Print JSON", false).allowExcessArguments().action(async (slug, options) => {
|
|
9170
|
+
if (options.queue) {
|
|
9171
|
+
const { artistsBioQueueCommand: artistsBioQueueCommand2 } = await Promise.resolve().then(() => (init_admin_artists(), exports_admin_artists));
|
|
9172
|
+
await runEntityBioQueue("artist", options, artistsBioQueueCommand2);
|
|
9173
|
+
return;
|
|
9174
|
+
}
|
|
9175
|
+
const { describeArtistCommand: describeArtistCommand2 } = await Promise.resolve().then(() => (init_admin_artists(), exports_admin_artists));
|
|
9176
|
+
await runEntityDescribe("artist", slug, options, describeArtistCommand2);
|
|
9177
|
+
});
|
|
9178
|
+
const labels = configureCommand(admin.command("labels").description("Label entity commands (the voiced bio)"));
|
|
9179
|
+
labels.action(() => {
|
|
9180
|
+
labels.outputHelp();
|
|
9181
|
+
});
|
|
9182
|
+
labels.command("describe").description("Author the voiced bio for a label (fills an empty bio only)").argument("[slug]").option("--queue", "Show the bio worklist (labels with findings but no bio), oldest first", false).option("--limit <limit>", "Number of labels to show with --queue", "50").option("--bio <text>", "The voice-gated bio paragraph").option("--bio-file <file>", "Read the bio from a file").option("--prompt-version <n>", "The prompt-registry version that authored the bio (the sweep sends this; it is the bio's provenance)").option("--dry-run", "Run the voice gate and report the verdict without storing anything", false).option("--json", "Print JSON", false).allowExcessArguments().action(async (slug, options) => {
|
|
9183
|
+
if (options.queue) {
|
|
9184
|
+
const { labelsBioQueueCommand: labelsBioQueueCommand2 } = await Promise.resolve().then(() => (init_admin_labels(), exports_admin_labels));
|
|
9185
|
+
await runEntityBioQueue("label", options, labelsBioQueueCommand2);
|
|
9186
|
+
return;
|
|
9187
|
+
}
|
|
9188
|
+
const { describeLabelCommand: describeLabelCommand2 } = await Promise.resolve().then(() => (init_admin_labels(), exports_admin_labels));
|
|
9189
|
+
await runEntityDescribe("label", slug, options, describeLabelCommand2);
|
|
9190
|
+
});
|
|
9082
9191
|
const migrations = configureCommand(admin.command("migrations").description("One-off operator data migrations"));
|
|
9083
9192
|
migrations.action(() => {
|
|
9084
9193
|
migrations.outputHelp();
|
|
@@ -9200,6 +9309,49 @@ async function runTrackNote(idOrLogId, options, trackNoteCommand2) {
|
|
|
9200
9309
|
console.log(`Authored the note for ${result.logId}:`);
|
|
9201
9310
|
console.log(` ${result.note}`);
|
|
9202
9311
|
}
|
|
9312
|
+
async function runEntityDescribe(kind, slug, options, describeCommand) {
|
|
9313
|
+
const bio = options.bioFile ? readFileSync7(options.bioFile, "utf8") : options.bio;
|
|
9314
|
+
if (!slug || !bio || !bio.trim()) {
|
|
9315
|
+
throw new Error(`Usage: fluncle admin ${kind}s describe <slug> (--bio <text> | --bio-file <file>) [--dry-run] [--json]`);
|
|
9316
|
+
}
|
|
9317
|
+
const result = await describeCommand(slug, {
|
|
9318
|
+
bio: bio.trim(),
|
|
9319
|
+
dryRun: options.dryRun,
|
|
9320
|
+
promptVersion: parsePromptVersion(options.promptVersion)
|
|
9321
|
+
});
|
|
9322
|
+
if (options.json) {
|
|
9323
|
+
printJson(result);
|
|
9324
|
+
return;
|
|
9325
|
+
}
|
|
9326
|
+
if (result.skipped) {
|
|
9327
|
+
console.log(`A bio is already on file for ${result.slug}. The operator's bio stands.`);
|
|
9328
|
+
return;
|
|
9329
|
+
}
|
|
9330
|
+
if (result.dryRun) {
|
|
9331
|
+
console.log(`The voice gate passed for ${result.slug}. Nothing was stored (dry run).`);
|
|
9332
|
+
console.log(` ${result.bio}`);
|
|
9333
|
+
return;
|
|
9334
|
+
}
|
|
9335
|
+
console.log(`Authored the bio for ${result.slug}:`);
|
|
9336
|
+
console.log(` ${result.bio}`);
|
|
9337
|
+
}
|
|
9338
|
+
async function runEntityBioQueue(kind, options, queueCommand2) {
|
|
9339
|
+
const limit = options.limit ? Number.parseInt(options.limit, 10) : 50;
|
|
9340
|
+
const items = await queueCommand2(Number.isFinite(limit) ? limit : 50);
|
|
9341
|
+
if (options.json) {
|
|
9342
|
+
printJson(items);
|
|
9343
|
+
return;
|
|
9344
|
+
}
|
|
9345
|
+
if (items.length === 0) {
|
|
9346
|
+
console.log(`No ${kind}s awaiting a bio.`);
|
|
9347
|
+
return;
|
|
9348
|
+
}
|
|
9349
|
+
const noun = items.length === 1 ? kind : `${kind}s`;
|
|
9350
|
+
console.log(`${items.length} ${noun} awaiting a bio, oldest first:`);
|
|
9351
|
+
for (const item of items) {
|
|
9352
|
+
console.log(` ${item.slug} ${item.name}`);
|
|
9353
|
+
}
|
|
9354
|
+
}
|
|
9203
9355
|
async function runTrackSimilar(idOrLogId, options, trackSimilarCommand2) {
|
|
9204
9356
|
if (!idOrLogId) {
|
|
9205
9357
|
throw new Error("Missing id. Usage: fluncle tracks similar <track_id|log_id> [--limit <n>] [--json]");
|
|
@@ -10771,6 +10923,44 @@ async function runNoteGate(options, noteGateCommand2) {
|
|
|
10771
10923
|
}
|
|
10772
10924
|
console.log(`The echo gate: a lift is ${gate.minPhraseWords}+ shared words; an echo is ${Math.round(gate.maxOverlap * 100)}%+ of a neighbour's words.`);
|
|
10773
10925
|
}
|
|
10926
|
+
async function runObservationHeld(options, observationHeldCommand2) {
|
|
10927
|
+
const { gate, rejections } = await observationHeldCommand2({ settled: options.settled === true });
|
|
10928
|
+
if (options.json) {
|
|
10929
|
+
printJson({ gate, ok: true, rejections });
|
|
10930
|
+
return;
|
|
10931
|
+
}
|
|
10932
|
+
if (rejections.length === 0) {
|
|
10933
|
+
console.log(options.settled ? "Nothing ruled on yet." : "Nothing held back. The gate is quiet.");
|
|
10934
|
+
return;
|
|
10935
|
+
}
|
|
10936
|
+
console.log(`The gate sits at ${gate.minPhraseWords} lifted words / ${Math.round(gate.maxOverlap * 100)}% overlap.`);
|
|
10937
|
+
for (const held of rejections) {
|
|
10938
|
+
const ruled = held.resolution ? ` [${held.resolution}]` : "";
|
|
10939
|
+
const bounced = held.attempts > 1 ? ` (bounced ${held.attempts}x)` : "";
|
|
10940
|
+
console.log("");
|
|
10941
|
+
console.log(`${held.logId ?? held.trackId} ${held.title}${bounced}${ruled}`);
|
|
10942
|
+
console.log(` wrote: ${held.script}`);
|
|
10943
|
+
if (held.phrase) {
|
|
10944
|
+
console.log(` lifted: "${held.phrase}" from ${held.neighborLogId ?? "a neighbour"}`);
|
|
10945
|
+
} else {
|
|
10946
|
+
console.log(` reuses: ${Math.round(held.overlap * 100)}% of ${held.neighborLogId ?? "a neighbour"}'s words`);
|
|
10947
|
+
}
|
|
10948
|
+
console.log(` judged at: ${held.minPhraseWords} words / ${Math.round(held.maxOverlap * 100)}%`);
|
|
10949
|
+
}
|
|
10950
|
+
}
|
|
10951
|
+
async function runObservationGate(options, observationGateCommand2) {
|
|
10952
|
+
const minPhraseWords = options.minPhraseWords === undefined ? undefined : Number(options.minPhraseWords);
|
|
10953
|
+
const maxOverlap = options.maxOverlap === undefined ? undefined : Number(options.maxOverlap);
|
|
10954
|
+
const gate = await observationGateCommand2({
|
|
10955
|
+
...maxOverlap === undefined ? {} : { maxOverlap },
|
|
10956
|
+
...minPhraseWords === undefined ? {} : { minPhraseWords }
|
|
10957
|
+
});
|
|
10958
|
+
if (options.json) {
|
|
10959
|
+
printJson({ gate, ok: true });
|
|
10960
|
+
return;
|
|
10961
|
+
}
|
|
10962
|
+
console.log(`The observation echo gate: a lift is ${gate.minPhraseWords}+ shared words; an echo is ${Math.round(gate.maxOverlap * 100)}%+ of a neighbour's words.`);
|
|
10963
|
+
}
|
|
10774
10964
|
async function runGalaxyMapRead(options, galaxyMapReadCommand2) {
|
|
10775
10965
|
const galaxies = await galaxyMapReadCommand2();
|
|
10776
10966
|
if (options.json) {
|
|
@@ -11343,6 +11533,8 @@ var stringOptions = new Set([
|
|
|
11343
11533
|
"--analyzed-from",
|
|
11344
11534
|
"--at",
|
|
11345
11535
|
"--audio",
|
|
11536
|
+
"--bio",
|
|
11537
|
+
"--bio-file",
|
|
11346
11538
|
"--body",
|
|
11347
11539
|
"--body-file",
|
|
11348
11540
|
"--bpm",
|
package/package.json
CHANGED