fluncle 0.114.0 → 0.116.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.
Files changed (2) hide show
  1. package/bin/fluncle.mjs +181 -4
  2. 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.114.0".trim() ? "0.114.0".trim() : "0.1.0";
560
+ currentVersion = "0.116.0".trim() ? "0.116.0".trim() : "0.1.0";
561
561
  });
562
562
 
563
563
  // src/update-notifier.ts
@@ -1042,6 +1042,48 @@ var init_artists = __esm(() => {
1042
1042
  init_api();
1043
1043
  });
1044
1044
 
1045
+ // src/commands/galaxies.ts
1046
+ var exports_galaxies = {};
1047
+ __export(exports_galaxies, {
1048
+ galaxyMapWriteCommand: () => galaxyMapWriteCommand,
1049
+ galaxyMapReadCommand: () => galaxyMapReadCommand,
1050
+ galaxyGetCommand: () => galaxyGetCommand,
1051
+ galaxyEmbeddingsCommand: () => galaxyEmbeddingsCommand,
1052
+ galaxiesListCommand: () => galaxiesListCommand
1053
+ });
1054
+ async function galaxiesListCommand() {
1055
+ const response = await publicApiGet("/api/v1/galaxies");
1056
+ return response.galaxies;
1057
+ }
1058
+ async function galaxyGetCommand(slug) {
1059
+ const response = await publicApiGet(`/api/v1/galaxies/${encodeURIComponent(slug)}`);
1060
+ return { findings: response.findings, galaxy: response.galaxy };
1061
+ }
1062
+ async function galaxyMapReadCommand() {
1063
+ const response = await adminApiGet("/api/admin/galaxies");
1064
+ return response.galaxies;
1065
+ }
1066
+ async function galaxyEmbeddingsCommand(options) {
1067
+ const params = new URLSearchParams;
1068
+ if (options.cursor) {
1069
+ params.set("cursor", options.cursor);
1070
+ }
1071
+ if (options.limit) {
1072
+ params.set("limit", options.limit);
1073
+ }
1074
+ const query = params.toString();
1075
+ return adminApiGet(`/api/admin/tracks/embeddings${query ? `?${query}` : ""}`);
1076
+ }
1077
+ async function galaxyMapWriteCommand(clusters) {
1078
+ const response = await adminApiPut("/api/admin/galaxies/map", {
1079
+ clusters
1080
+ });
1081
+ return response.galaxies;
1082
+ }
1083
+ var init_galaxies = __esm(() => {
1084
+ init_api();
1085
+ });
1086
+
1045
1087
  // src/commands/mixtape-api.ts
1046
1088
  async function mixtapeListCommand() {
1047
1089
  const response = await adminApiGet("/api/admin/mixtapes");
@@ -2209,7 +2251,7 @@ function parseVersion2(version) {
2209
2251
  var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
2210
2252
  var init_version2 = __esm(() => {
2211
2253
  init_output();
2212
- currentVersion2 = "0.114.0".trim() ? "0.114.0".trim() : "0.1.0";
2254
+ currentVersion2 = "0.116.0".trim() ? "0.116.0".trim() : "0.1.0";
2213
2255
  });
2214
2256
 
2215
2257
  // ../../packages/registry/src/index.ts
@@ -2875,6 +2917,17 @@ var init_src = __esm(() => {
2875
2917
  probeConfig: { cadenceMs: 10 * MINUTE_MS, cronName: "fluncle-note", kind: "cron" },
2876
2918
  weights: { status: "hidden" }
2877
2919
  },
2920
+ {
2921
+ command: "fluncle admin submissions triage",
2922
+ exposedContent: [
2923
+ "pre-chew a pending crew submission → an advisory queue verdict, fill-first (hybrid: one claude -p call)"
2924
+ ],
2925
+ kind: "cron",
2926
+ name: "cron.triage",
2927
+ operatorNotes: "every 15m. Hybrid --no-agent; a deterministic archive dedupe + DnB-plausibility heuristic feeds one claude -p phrasing, length-gated. Writes the verdict onto a PENDING submission so it lands in the /admin attention queue already assessed; approve/reject stays operator tier. Source: docs/agents/hermes/scripts/triage-sweep.{sh,ts}.",
2928
+ probeConfig: { cadenceMs: 15 * MINUTE_MS, cronName: "fluncle-triage", kind: "cron" },
2929
+ weights: { status: "hidden" }
2930
+ },
2878
2931
  {
2879
2932
  command: "fluncle admin logbook gaps",
2880
2933
  exposedContent: [
@@ -3270,6 +3323,9 @@ async function trackUpdateCommand(trackId, options) {
3270
3323
  if (options.embedding !== undefined) {
3271
3324
  body.embedding = options.embedding;
3272
3325
  }
3326
+ if (options.galaxyId !== undefined) {
3327
+ body.galaxyId = options.galaxyId;
3328
+ }
3273
3329
  if (options.note !== undefined) {
3274
3330
  body.note = options.note;
3275
3331
  }
@@ -3462,6 +3518,9 @@ async function trackUpdateCommand2(trackId, options) {
3462
3518
  if (options.embedding !== undefined) {
3463
3519
  body.embedding = options.embedding;
3464
3520
  }
3521
+ if (options.galaxyId !== undefined) {
3522
+ body.galaxyId = options.galaxyId;
3523
+ }
3465
3524
  if (options.note !== undefined) {
3466
3525
  body.note = options.note;
3467
3526
  }
@@ -7768,6 +7827,10 @@ function addListenCommands(program2) {
7768
7827
  const { artistsListCommand: artistsListCommand2, artistsGetCommand: artistsGetCommand2 } = await Promise.resolve().then(() => (init_artists(), exports_artists));
7769
7828
  await runArtists(slug, options, { artistsGetCommand: artistsGetCommand2, artistsListCommand: artistsListCommand2 });
7770
7829
  });
7830
+ program2.command("galaxies").description("Wander Fluncle's sonic galaxies").argument("[slug]", "Galaxy slug (omit for the full map)").option("--json", "Print JSON", false).action(async (slug, options) => {
7831
+ const { galaxiesListCommand: galaxiesListCommand2, galaxyGetCommand: galaxyGetCommand2 } = await Promise.resolve().then(() => (init_galaxies(), exports_galaxies));
7832
+ await runGalaxies(slug, options, { galaxiesListCommand: galaxiesListCommand2, galaxyGetCommand: galaxyGetCommand2 });
7833
+ });
7771
7834
  program2.command("mixtapes").description("Fluncle's checkpoint sets").option("--json", "Print JSON", false).action(async (options) => {
7772
7835
  const { mixtapesCommand: mixtapesCommand2 } = await Promise.resolve().then(() => (init_mixtapes(), exports_mixtapes));
7773
7836
  await runMixtapes(options, mixtapesCommand2);
@@ -7901,7 +7964,7 @@ function addAdminCommands(program2) {
7901
7964
  const { mixableOrderCommand: mixableOrderCommand2 } = await Promise.resolve().then(() => (init_admin_tracks(), exports_admin_tracks));
7902
7965
  await runMixableOrder(logIds, options, mixableOrderCommand2);
7903
7966
  });
7904
- adminTrack.command("update").description("Certify a track into the archive").argument("[trackId]").option("--analyzed-at <iso>", "Analysis-write ISO timestamp (BPM/key provenance)").option("--analyzed-from <class>", "Audio class BPM/key were analyzed from: full or preview").option("--bpm <number>", "Track BPM").option("--bpm-confidence <number>", "Analyzer confidence in the BPM (0..1)").option("--bpm-source <source>", "Where the BPM came from (analyzer bpmSource)").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("--key-confidence <number>", "Analyzer confidence in the key (0..1)").option("--key-source <source>", "Where the key came from (analyzer keySource)").option("--note <text>", "Operator note").option("--status <status>", "Enrichment status").option("--video-url <url>", "Rendered video URL").allowExcessArguments().action(async (trackId, options) => {
7967
+ adminTrack.command("update").description("Certify a track into the archive").argument("[trackId]").option("--analyzed-at <iso>", "Analysis-write ISO timestamp (BPM/key provenance)").option("--analyzed-from <class>", "Audio class BPM/key were analyzed from: full or preview").option("--bpm <number>", "Track BPM").option("--bpm-confidence <number>", "Analyzer confidence in the BPM (0..1)").option("--bpm-source <source>", "Where the BPM came from (analyzer bpmSource)").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("--galaxy-id <id>", "Sonic galaxy assignment (empty string clears it)").option("--json", "Print JSON", false).option("--key <key>", "Musical key").option("--key-confidence <number>", "Analyzer confidence in the key (0..1)").option("--key-source <source>", "Where the key came from (analyzer keySource)").option("--note <text>", "Operator note").option("--status <status>", "Enrichment status").option("--video-url <url>", "Rendered video URL").allowExcessArguments().action(async (trackId, options) => {
7905
7968
  const { trackUpdateCommand: trackUpdateCommand3 } = await Promise.resolve().then(() => (init_track(), exports_track));
7906
7969
  await runTrackUpdate(trackId, options, trackUpdateCommand3);
7907
7970
  });
@@ -8143,6 +8206,22 @@ function addAdminCommands(program2) {
8143
8206
  artists.action(() => {
8144
8207
  artists.outputHelp();
8145
8208
  });
8209
+ const galaxies = configureCommand(admin.command("galaxies").description("Sonic galaxy map (cluster sweep) commands"));
8210
+ galaxies.action(() => {
8211
+ galaxies.outputHelp();
8212
+ });
8213
+ galaxies.command("map").description("Read the full galaxy map (named + unnamed + retired, with centroids)").option("--json", "Print JSON", false).action(async (options) => {
8214
+ const { galaxyMapReadCommand: galaxyMapReadCommand2 } = await Promise.resolve().then(() => (init_galaxies(), exports_galaxies));
8215
+ await runGalaxyMapRead(options, galaxyMapReadCommand2);
8216
+ });
8217
+ galaxies.command("embeddings").description("Read a cursor page of the embedded corpus (the cluster engine's input)").option("--cursor <cursor>", "Opaque cursor from a prior page's nextCursor").option("--limit <limit>", "Page size (default 200, clamped to 500)").option("--json", "Print JSON", false).action(async (options) => {
8218
+ const { galaxyEmbeddingsCommand: galaxyEmbeddingsCommand2 } = await Promise.resolve().then(() => (init_galaxies(), exports_galaxies));
8219
+ await runGalaxyEmbeddings(options, galaxyEmbeddingsCommand2);
8220
+ });
8221
+ galaxies.command("set-map").description("Write the galaxy map transactionally (mint new ids, upsert centroids, retire)").requiredOption("--file <file>", "Path to the clusters JSON ({ clusters: [...] } or a bare array)").option("--json", "Print JSON", false).action(async (options) => {
8222
+ const { galaxyMapWriteCommand: galaxyMapWriteCommand2 } = await Promise.resolve().then(() => (init_galaxies(), exports_galaxies));
8223
+ await runGalaxyMapWrite(options, galaxyMapWriteCommand2);
8224
+ });
8146
8225
  const backfill = configureCommand(admin.command("backfills").description("Backfill operator-only archives"));
8147
8226
  backfill.action(() => {
8148
8227
  backfill.outputHelp();
@@ -8792,6 +8871,7 @@ async function runTrackUpdate(trackId, options, trackUpdateCommand3) {
8792
8871
  bpmSource: options.bpmSource,
8793
8872
  embedding,
8794
8873
  features: options.features,
8874
+ galaxyId: options.galaxyId,
8795
8875
  key: options.key,
8796
8876
  keyConfidence,
8797
8877
  keySource: options.keySource,
@@ -9155,6 +9235,71 @@ async function runArtists(slug, options, commands) {
9155
9235
  console.log(`${a.name.padEnd(40)} ${String(a.findingCount).padStart(3)} finding${a.findingCount === 1 ? "" : "s"}`);
9156
9236
  }
9157
9237
  }
9238
+ async function runGalaxies(slug, options, commands) {
9239
+ if (slug) {
9240
+ const { findings, galaxy } = await commands.galaxyGetCommand(slug);
9241
+ if (options.json) {
9242
+ printJson({ findings, galaxy, ok: true });
9243
+ return;
9244
+ }
9245
+ console.log(`${galaxy.name} (${galaxy.slug})`);
9246
+ console.log(`${galaxy.memberCount} finding${galaxy.memberCount === 1 ? "" : "s"}`);
9247
+ for (const finding of findings) {
9248
+ const coordinate3 = finding.logId ? `${finding.logId} ` : "";
9249
+ console.log(` ${coordinate3}${finding.artists.join(", ")} \u2014 ${finding.title}`);
9250
+ }
9251
+ return;
9252
+ }
9253
+ const galaxies = await commands.galaxiesListCommand();
9254
+ if (options.json) {
9255
+ printJson({ galaxies, ok: true });
9256
+ return;
9257
+ }
9258
+ if (galaxies.length === 0) {
9259
+ console.log("No galaxies named yet. Quiet map tonight.");
9260
+ return;
9261
+ }
9262
+ for (const galaxy of galaxies) {
9263
+ console.log(`${galaxy.name.padEnd(40)} ${String(galaxy.memberCount).padStart(3)} finding${galaxy.memberCount === 1 ? "" : "s"}`);
9264
+ }
9265
+ }
9266
+ async function runGalaxyMapRead(options, galaxyMapReadCommand2) {
9267
+ const galaxies = await galaxyMapReadCommand2();
9268
+ if (options.json) {
9269
+ printJson({ galaxies, ok: true });
9270
+ return;
9271
+ }
9272
+ if (galaxies.length === 0) {
9273
+ console.log("No galaxies on the map yet.");
9274
+ return;
9275
+ }
9276
+ for (const galaxy of galaxies) {
9277
+ const name = galaxy.name ?? "(unnamed)";
9278
+ const retired = galaxy.retiredAt ? " [retired]" : "";
9279
+ console.log(`${galaxy.id} ${galaxy.handle.padEnd(30)} ${name.padEnd(24)} ${String(galaxy.memberCount).padStart(4)} members${retired}`);
9280
+ }
9281
+ }
9282
+ async function runGalaxyEmbeddings(options, galaxyEmbeddingsCommand2) {
9283
+ const result = await galaxyEmbeddingsCommand2({ cursor: options.cursor, limit: options.limit });
9284
+ if (options.json) {
9285
+ printJson(result);
9286
+ return;
9287
+ }
9288
+ console.log(`${result.embeddings.length} embedding(s)${result.nextCursor ? ` \xB7 nextCursor: ${result.nextCursor}` : " \xB7 end of corpus"}`);
9289
+ }
9290
+ async function runGalaxyMapWrite(options, galaxyMapWriteCommand2) {
9291
+ const raw = JSON.parse(readFileSync6(options.file, "utf8"));
9292
+ const clusters = Array.isArray(raw) || raw === null ? raw : raw.clusters;
9293
+ if (!Array.isArray(clusters)) {
9294
+ throw new Error("Invalid --file: expected { clusters: [...] } or a JSON array of cluster rows");
9295
+ }
9296
+ const galaxies = await galaxyMapWriteCommand2(clusters);
9297
+ if (options.json) {
9298
+ printJson({ galaxies, ok: true });
9299
+ return;
9300
+ }
9301
+ console.log(`Wrote ${clusters.length} cluster(s); the map now holds ${galaxies.length} galaxy(ies).`);
9302
+ }
9158
9303
  async function runMixtapes(options, mixtapesCommand2) {
9159
9304
  const mixtapes = await mixtapesCommand2();
9160
9305
  if (options.json) {
@@ -9649,13 +9794,24 @@ function normalizeCommanderError(error) {
9649
9794
  var stringOptions = new Set([
9650
9795
  "--analyzed-at",
9651
9796
  "--analyzed-from",
9797
+ "--at",
9798
+ "--audio",
9799
+ "--body",
9800
+ "--body-file",
9652
9801
  "--bpm",
9653
9802
  "--bpm-confidence",
9654
9803
  "--bpm-source",
9655
9804
  "--composition",
9805
+ "--content-file",
9806
+ "--context-note",
9656
9807
  "--cover",
9808
+ "--cues-file",
9809
+ "--cursor",
9657
9810
  "--dir",
9658
9811
  "--duration-ms",
9812
+ "--duration-target-sec",
9813
+ "--embedding",
9814
+ "--embedding-file",
9659
9815
  "--features",
9660
9816
  "--file",
9661
9817
  "--footage",
@@ -9664,29 +9820,50 @@ var stringOptions = new Set([
9664
9820
  "--footage-notext",
9665
9821
  "--footage-social",
9666
9822
  "--from",
9823
+ "--galaxy-id",
9824
+ "--has-key",
9667
9825
  "--intent",
9668
9826
  "--key",
9669
9827
  "--key-confidence",
9670
9828
  "--key-source",
9829
+ "--kind",
9671
9830
  "--limit",
9672
9831
  "--metrics",
9673
9832
  "--mime",
9833
+ "--model",
9674
9834
  "--note",
9835
+ "--order",
9836
+ "--parent-id",
9675
9837
  "--plate",
9676
9838
  "--plate-background",
9677
9839
  "--platform",
9678
9840
  "--poster",
9679
9841
  "--props",
9680
9842
  "--query",
9843
+ "--reasoning",
9681
9844
  "--recorded-at",
9845
+ "--recording",
9682
9846
  "--render",
9683
9847
  "--scene",
9684
9848
  "--scheduled-for",
9849
+ "--script",
9850
+ "--script-file",
9851
+ "--seed",
9685
9852
  "--soundcloud-url",
9686
9853
  "--source",
9687
9854
  "--status",
9855
+ "--subject",
9856
+ "--title",
9857
+ "--token",
9858
+ "--tracklist-file",
9688
9859
  "--url",
9689
- "--video-url"
9860
+ "--verdict",
9861
+ "--verdict-file",
9862
+ "--video",
9863
+ "--video-url",
9864
+ "--voice-id",
9865
+ "--window-since",
9866
+ "--window-until"
9690
9867
  ]);
9691
9868
  var rootHelpSections = `
9692
9869
 
package/package.json CHANGED
@@ -31,5 +31,5 @@
31
31
  "url": "git+https://github.com/mauricekleine/fluncle.git"
32
32
  },
33
33
  "type": "module",
34
- "version": "0.114.0"
34
+ "version": "0.116.0"
35
35
  }