fluncle 0.154.0 → 0.156.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 +165 -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.156.0".trim() ? "0.156.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.156.0".trim() ? "0.156.0".trim() : "0.1.0";
|
|
2193
2193
|
});
|
|
2194
2194
|
|
|
2195
2195
|
// ../../packages/registry/src/index.ts
|
|
@@ -3025,6 +3025,28 @@ var init_src = __esm(() => {
|
|
|
3025
3025
|
probeConfig: { cadenceMs: 10 * MINUTE_MS, cronName: "fluncle-note", kind: "cron" },
|
|
3026
3026
|
weights: { status: "hidden" }
|
|
3027
3027
|
},
|
|
3028
|
+
{
|
|
3029
|
+
command: "fluncle admin artists describe --queue",
|
|
3030
|
+
exposedContent: [
|
|
3031
|
+
"auto-author the /artist/<slug> voiced bio, fill-empty-only (hybrid: one claude -p call)"
|
|
3032
|
+
],
|
|
3033
|
+
kind: "cron",
|
|
3034
|
+
name: "cron.artist-bio",
|
|
3035
|
+
operatorNotes: "every 30m. Hybrid --no-agent; one claude -p authors the paragraph off best-effort Firecrawl facts + identity. Never clobbers an operator bio. Box activation operator-gated. Source: docs/agents/hermes/scripts/{entity-bio-sweep.ts,artist-bio-sweep.sh}.",
|
|
3036
|
+
probeConfig: { cadenceMs: 30 * MINUTE_MS, cronName: "fluncle-artist-bio", kind: "cron" },
|
|
3037
|
+
weights: { status: "hidden" }
|
|
3038
|
+
},
|
|
3039
|
+
{
|
|
3040
|
+
command: "fluncle admin labels describe --queue",
|
|
3041
|
+
exposedContent: [
|
|
3042
|
+
"auto-author the /label/<slug> voiced bio, fill-empty-only (hybrid: one claude -p call)"
|
|
3043
|
+
],
|
|
3044
|
+
kind: "cron",
|
|
3045
|
+
name: "cron.label-bio",
|
|
3046
|
+
operatorNotes: "every 30m. Hybrid --no-agent; one claude -p authors the paragraph off best-effort Firecrawl facts + identity. Never clobbers an operator bio. Box activation operator-gated. Source: docs/agents/hermes/scripts/{entity-bio-sweep.ts,label-bio-sweep.sh}.",
|
|
3047
|
+
probeConfig: { cadenceMs: 30 * MINUTE_MS, cronName: "fluncle-label-bio", kind: "cron" },
|
|
3048
|
+
weights: { status: "hidden" }
|
|
3049
|
+
},
|
|
3028
3050
|
{
|
|
3029
3051
|
command: "fluncle admin submissions triage",
|
|
3030
3052
|
exposedContent: [
|
|
@@ -5896,9 +5918,33 @@ var exports_admin_artists = {};
|
|
|
5896
5918
|
__export(exports_admin_artists, {
|
|
5897
5919
|
resolveArtistCommand: () => resolveArtistCommand,
|
|
5898
5920
|
listArtistsCommand: () => listArtistsCommand,
|
|
5921
|
+
draftArtistBioCommand: () => draftArtistBioCommand,
|
|
5922
|
+
describeArtistCommand: () => describeArtistCommand,
|
|
5923
|
+
buildBioBody: () => buildBioBody,
|
|
5899
5924
|
backfillArtistsCommand: () => backfillArtistsCommand,
|
|
5900
|
-
backfillArtistImagesCommand: () => backfillArtistImagesCommand
|
|
5925
|
+
backfillArtistImagesCommand: () => backfillArtistImagesCommand,
|
|
5926
|
+
artistsBioQueueCommand: () => artistsBioQueueCommand
|
|
5901
5927
|
});
|
|
5928
|
+
function buildBioBody(options) {
|
|
5929
|
+
const body = { bio: options.bio };
|
|
5930
|
+
if (options.dryRun) {
|
|
5931
|
+
body.dryRun = true;
|
|
5932
|
+
}
|
|
5933
|
+
if (typeof options.promptVersion === "number") {
|
|
5934
|
+
body.promptVersion = options.promptVersion;
|
|
5935
|
+
}
|
|
5936
|
+
return body;
|
|
5937
|
+
}
|
|
5938
|
+
async function describeArtistCommand(slug, options) {
|
|
5939
|
+
return adminApiPost(`/api/admin/artists/${encodeURIComponent(slug)}/bio`, buildBioBody(options));
|
|
5940
|
+
}
|
|
5941
|
+
async function draftArtistBioCommand(slug) {
|
|
5942
|
+
return adminApiGet(`/api/admin/artists/${encodeURIComponent(slug)}/bio-draft`);
|
|
5943
|
+
}
|
|
5944
|
+
async function artistsBioQueueCommand(limit) {
|
|
5945
|
+
const response = await adminApiGet(`/api/admin/artists/bio-queue?limit=${limit}`);
|
|
5946
|
+
return response.artists;
|
|
5947
|
+
}
|
|
5902
5948
|
async function listArtistsCommand(limit, cursor) {
|
|
5903
5949
|
const params = new URLSearchParams({ limit: String(limit) });
|
|
5904
5950
|
if (cursor) {
|
|
@@ -5927,11 +5973,39 @@ var init_admin_artists = __esm(() => {
|
|
|
5927
5973
|
init_api();
|
|
5928
5974
|
});
|
|
5929
5975
|
|
|
5976
|
+
// src/commands/admin-artists.ts
|
|
5977
|
+
function buildBioBody2(options) {
|
|
5978
|
+
const body = { bio: options.bio };
|
|
5979
|
+
if (options.dryRun) {
|
|
5980
|
+
body.dryRun = true;
|
|
5981
|
+
}
|
|
5982
|
+
if (typeof options.promptVersion === "number") {
|
|
5983
|
+
body.promptVersion = options.promptVersion;
|
|
5984
|
+
}
|
|
5985
|
+
return body;
|
|
5986
|
+
}
|
|
5987
|
+
var init_admin_artists2 = __esm(() => {
|
|
5988
|
+
init_api();
|
|
5989
|
+
});
|
|
5990
|
+
|
|
5930
5991
|
// src/commands/admin-labels.ts
|
|
5931
5992
|
var exports_admin_labels = {};
|
|
5932
5993
|
__export(exports_admin_labels, {
|
|
5994
|
+
labelsBioQueueCommand: () => labelsBioQueueCommand,
|
|
5995
|
+
draftLabelBioCommand: () => draftLabelBioCommand,
|
|
5996
|
+
describeLabelCommand: () => describeLabelCommand,
|
|
5933
5997
|
backfillLabelImagesCommand: () => backfillLabelImagesCommand
|
|
5934
5998
|
});
|
|
5999
|
+
async function describeLabelCommand(slug, options) {
|
|
6000
|
+
return adminApiPost(`/api/admin/labels/${encodeURIComponent(slug)}/bio`, buildBioBody2(options));
|
|
6001
|
+
}
|
|
6002
|
+
async function draftLabelBioCommand(slug) {
|
|
6003
|
+
return adminApiGet(`/api/admin/labels/${encodeURIComponent(slug)}/bio-draft`);
|
|
6004
|
+
}
|
|
6005
|
+
async function labelsBioQueueCommand(limit) {
|
|
6006
|
+
const response = await adminApiGet(`/api/admin/labels/bio-queue?limit=${limit}`);
|
|
6007
|
+
return response.labels;
|
|
6008
|
+
}
|
|
5935
6009
|
async function backfillLabelImagesCommand(limit, dryRun, cursor) {
|
|
5936
6010
|
const params = new URLSearchParams({ dryRun: String(dryRun), limit: String(limit) });
|
|
5937
6011
|
if (cursor) {
|
|
@@ -5941,6 +6015,7 @@ async function backfillLabelImagesCommand(limit, dryRun, cursor) {
|
|
|
5941
6015
|
}
|
|
5942
6016
|
var init_admin_labels = __esm(() => {
|
|
5943
6017
|
init_api();
|
|
6018
|
+
init_admin_artists2();
|
|
5944
6019
|
});
|
|
5945
6020
|
|
|
5946
6021
|
// src/commands/admin-covers.ts
|
|
@@ -9121,6 +9196,36 @@ function addAdminCommands(program2) {
|
|
|
9121
9196
|
const { resolveArtistCommand: resolveArtistCommand2 } = await Promise.resolve().then(() => (init_admin_artists(), exports_admin_artists));
|
|
9122
9197
|
await runArtistResolve(artistId, options, resolveArtistCommand2);
|
|
9123
9198
|
});
|
|
9199
|
+
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) => {
|
|
9200
|
+
if (options.queue) {
|
|
9201
|
+
const { artistsBioQueueCommand: artistsBioQueueCommand2 } = await Promise.resolve().then(() => (init_admin_artists(), exports_admin_artists));
|
|
9202
|
+
await runEntityBioQueue("artist", options, artistsBioQueueCommand2);
|
|
9203
|
+
return;
|
|
9204
|
+
}
|
|
9205
|
+
const { describeArtistCommand: describeArtistCommand2 } = await Promise.resolve().then(() => (init_admin_artists(), exports_admin_artists));
|
|
9206
|
+
await runEntityDescribe("artist", slug, options, describeArtistCommand2);
|
|
9207
|
+
});
|
|
9208
|
+
artists.command("draft-bio").description("Assemble the Worker-grounded bio prompt for an artist (the sweep's trigger)").argument("<slug>").option("--json", "Print JSON", false).allowExcessArguments().action(async (slug, options) => {
|
|
9209
|
+
const { draftArtistBioCommand: draftArtistBioCommand2 } = await Promise.resolve().then(() => (init_admin_artists(), exports_admin_artists));
|
|
9210
|
+
await runEntityBioDraft("artist", slug, options, draftArtistBioCommand2);
|
|
9211
|
+
});
|
|
9212
|
+
const labels = configureCommand(admin.command("labels").description("Label entity commands (the voiced bio)"));
|
|
9213
|
+
labels.action(() => {
|
|
9214
|
+
labels.outputHelp();
|
|
9215
|
+
});
|
|
9216
|
+
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) => {
|
|
9217
|
+
if (options.queue) {
|
|
9218
|
+
const { labelsBioQueueCommand: labelsBioQueueCommand2 } = await Promise.resolve().then(() => (init_admin_labels(), exports_admin_labels));
|
|
9219
|
+
await runEntityBioQueue("label", options, labelsBioQueueCommand2);
|
|
9220
|
+
return;
|
|
9221
|
+
}
|
|
9222
|
+
const { describeLabelCommand: describeLabelCommand2 } = await Promise.resolve().then(() => (init_admin_labels(), exports_admin_labels));
|
|
9223
|
+
await runEntityDescribe("label", slug, options, describeLabelCommand2);
|
|
9224
|
+
});
|
|
9225
|
+
labels.command("draft-bio").description("Assemble the Worker-grounded bio prompt for a label (the sweep's trigger)").argument("<slug>").option("--json", "Print JSON", false).allowExcessArguments().action(async (slug, options) => {
|
|
9226
|
+
const { draftLabelBioCommand: draftLabelBioCommand2 } = await Promise.resolve().then(() => (init_admin_labels(), exports_admin_labels));
|
|
9227
|
+
await runEntityBioDraft("label", slug, options, draftLabelBioCommand2);
|
|
9228
|
+
});
|
|
9124
9229
|
const migrations = configureCommand(admin.command("migrations").description("One-off operator data migrations"));
|
|
9125
9230
|
migrations.action(() => {
|
|
9126
9231
|
migrations.outputHelp();
|
|
@@ -9242,6 +9347,61 @@ async function runTrackNote(idOrLogId, options, trackNoteCommand2) {
|
|
|
9242
9347
|
console.log(`Authored the note for ${result.logId}:`);
|
|
9243
9348
|
console.log(` ${result.note}`);
|
|
9244
9349
|
}
|
|
9350
|
+
async function runEntityDescribe(kind, slug, options, describeCommand) {
|
|
9351
|
+
const bio = options.bioFile ? readFileSync7(options.bioFile, "utf8") : options.bio;
|
|
9352
|
+
if (!slug || !bio || !bio.trim()) {
|
|
9353
|
+
throw new Error(`Usage: fluncle admin ${kind}s describe <slug> (--bio <text> | --bio-file <file>) [--dry-run] [--json]`);
|
|
9354
|
+
}
|
|
9355
|
+
const result = await describeCommand(slug, {
|
|
9356
|
+
bio: bio.trim(),
|
|
9357
|
+
dryRun: options.dryRun,
|
|
9358
|
+
promptVersion: parsePromptVersion(options.promptVersion)
|
|
9359
|
+
});
|
|
9360
|
+
if (options.json) {
|
|
9361
|
+
printJson(result);
|
|
9362
|
+
return;
|
|
9363
|
+
}
|
|
9364
|
+
if (result.skipped) {
|
|
9365
|
+
console.log(`A bio is already on file for ${result.slug}. The operator's bio stands.`);
|
|
9366
|
+
return;
|
|
9367
|
+
}
|
|
9368
|
+
if (result.dryRun) {
|
|
9369
|
+
console.log(`The voice gate passed for ${result.slug}. Nothing was stored (dry run).`);
|
|
9370
|
+
console.log(` ${result.bio}`);
|
|
9371
|
+
return;
|
|
9372
|
+
}
|
|
9373
|
+
console.log(`Authored the bio for ${result.slug}:`);
|
|
9374
|
+
console.log(` ${result.bio}`);
|
|
9375
|
+
}
|
|
9376
|
+
async function runEntityBioQueue(kind, options, queueCommand2) {
|
|
9377
|
+
const limit = options.limit ? Number.parseInt(options.limit, 10) : 50;
|
|
9378
|
+
const items = await queueCommand2(Number.isFinite(limit) ? limit : 50);
|
|
9379
|
+
if (options.json) {
|
|
9380
|
+
printJson(items);
|
|
9381
|
+
return;
|
|
9382
|
+
}
|
|
9383
|
+
if (items.length === 0) {
|
|
9384
|
+
console.log(`No ${kind}s awaiting a bio.`);
|
|
9385
|
+
return;
|
|
9386
|
+
}
|
|
9387
|
+
const noun = items.length === 1 ? kind : `${kind}s`;
|
|
9388
|
+
console.log(`${items.length} ${noun} awaiting a bio, oldest first:`);
|
|
9389
|
+
for (const item of items) {
|
|
9390
|
+
console.log(` ${item.slug} ${item.name}`);
|
|
9391
|
+
}
|
|
9392
|
+
}
|
|
9393
|
+
async function runEntityBioDraft(kind, slug, options, draftCommand) {
|
|
9394
|
+
const draft = await draftCommand(slug);
|
|
9395
|
+
if (options.json) {
|
|
9396
|
+
printJson(draft);
|
|
9397
|
+
return;
|
|
9398
|
+
}
|
|
9399
|
+
if (!draft.found) {
|
|
9400
|
+
console.log(`No ${kind} with slug ${slug}.`);
|
|
9401
|
+
return;
|
|
9402
|
+
}
|
|
9403
|
+
console.log(`Drafted a bio prompt for ${draft.name} (${draft.findingCount} finding(s), facts: ${draft.hasFacts ? "yes" : "none"}, prompt v${draft.promptVersion}).`);
|
|
9404
|
+
}
|
|
9245
9405
|
async function runTrackSimilar(idOrLogId, options, trackSimilarCommand2) {
|
|
9246
9406
|
if (!idOrLogId) {
|
|
9247
9407
|
throw new Error("Missing id. Usage: fluncle tracks similar <track_id|log_id> [--limit <n>] [--json]");
|
|
@@ -11423,6 +11583,8 @@ var stringOptions = new Set([
|
|
|
11423
11583
|
"--analyzed-from",
|
|
11424
11584
|
"--at",
|
|
11425
11585
|
"--audio",
|
|
11586
|
+
"--bio",
|
|
11587
|
+
"--bio-file",
|
|
11426
11588
|
"--body",
|
|
11427
11589
|
"--body-file",
|
|
11428
11590
|
"--bpm",
|
package/package.json
CHANGED