fluncle 0.186.0 → 0.187.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 +185 -170
  2. 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.186.0".trim() ? "0.186.0".trim() : "0.1.0";
564
+ currentVersion = "0.187.0".trim() ? "0.187.0".trim() : "0.1.0";
565
565
  });
566
566
 
567
567
  // src/update-notifier.ts
@@ -965,7 +965,7 @@ async function fetchRecentPage(cursor, limit = 10) {
965
965
  if (cursor) {
966
966
  params.set("cursor", cursor);
967
967
  }
968
- const response = await publicApiGet(`/api/tracks?${params.toString()}`);
968
+ const response = await publicApiGet(`/api/v1/findings?${params.toString()}`);
969
969
  return {
970
970
  nextCursor: response.nextCursor,
971
971
  totalCount: response.totalCount,
@@ -980,7 +980,7 @@ async function recentCommand(limit) {
980
980
  if (cursor) {
981
981
  params.set("cursor", cursor);
982
982
  }
983
- const response = await publicApiGet(`/api/tracks?${params.toString()}`);
983
+ const response = await publicApiGet(`/api/v1/findings?${params.toString()}`);
984
984
  for (const apiTrack of response.tracks) {
985
985
  results.push(mapTrack(apiTrack));
986
986
  if (results.length >= limit) {
@@ -1287,7 +1287,7 @@ async function galaxyGetCommand(slug) {
1287
1287
  return { findings: response.findings, galaxy: response.galaxy };
1288
1288
  }
1289
1289
  async function galaxyMapReadCommand() {
1290
- const response = await adminApiGet("/api/admin/galaxies");
1290
+ const response = await adminApiGet("/api/v1/admin/galaxies");
1291
1291
  return response.galaxies;
1292
1292
  }
1293
1293
  async function galaxyEmbeddingsCommand(options) {
@@ -1299,10 +1299,10 @@ async function galaxyEmbeddingsCommand(options) {
1299
1299
  params.set("limit", options.limit);
1300
1300
  }
1301
1301
  const query = params.toString();
1302
- return adminApiGet(`/api/admin/tracks/embeddings${query ? `?${query}` : ""}`);
1302
+ return adminApiGet(`/api/v1/admin/tracks/embeddings${query ? `?${query}` : ""}`);
1303
1303
  }
1304
1304
  async function galaxyMapWriteCommand(clusters) {
1305
- const response = await adminApiPut("/api/admin/galaxies/map", {
1305
+ const response = await adminApiPut("/api/v1/admin/galaxies/map", {
1306
1306
  clusters
1307
1307
  });
1308
1308
  return response.galaxies;
@@ -1313,7 +1313,7 @@ var init_galaxies = __esm(() => {
1313
1313
 
1314
1314
  // src/commands/mixtape-api.ts
1315
1315
  async function mixtapeListCommand() {
1316
- const response = await adminApiGet("/api/admin/mixtapes");
1316
+ const response = await adminApiGet("/api/v1/admin/mixtapes");
1317
1317
  return response.mixtapes;
1318
1318
  }
1319
1319
  async function mixtapeGetCommand(idOrLogId) {
@@ -1380,20 +1380,20 @@ async function distributeYoutube(mixtapeId, videoPath, onProgress) {
1380
1380
  offset = 0;
1381
1381
  }
1382
1382
  onProgress?.("Recording the YouTube link");
1383
- await adminApiPost(`/api/admin/mixtapes/${encodeURIComponent(mixtapeId)}/youtube/finalize`, { videoId });
1383
+ await adminApiPost(`/api/v1/admin/mixtapes/${encodeURIComponent(mixtapeId)}/youtube/finalize`, { videoId });
1384
1384
  return { url: `https://youtu.be/${videoId}`, videoId };
1385
1385
  }
1386
1386
  async function publishYoutubeCommand(idOrLogId) {
1387
1387
  const mixtapeId = await resolveMixtapeId(idOrLogId);
1388
- const response = await adminApiPost(`/api/admin/mixtapes/${encodeURIComponent(mixtapeId)}/youtube/publish`);
1388
+ const response = await adminApiPost(`/api/v1/admin/mixtapes/${encodeURIComponent(mixtapeId)}/youtube/publish`);
1389
1389
  return { url: response.url };
1390
1390
  }
1391
1391
  async function resyncYoutube(mixtapeId) {
1392
- const response = await adminApiPost(`/api/admin/mixtapes/${encodeURIComponent(mixtapeId)}/youtube/resync`);
1392
+ const response = await adminApiPost(`/api/v1/admin/mixtapes/${encodeURIComponent(mixtapeId)}/youtube/resync`);
1393
1393
  return { url: response.url, videoId: response.videoId };
1394
1394
  }
1395
1395
  async function authYoutubeCommand() {
1396
- const response = await adminApiGet("/api/admin/youtube/auth/start");
1396
+ const response = await adminApiGet("/api/v1/admin/youtube/auth/start");
1397
1397
  console.log(`Open this YouTube authorization URL:
1398
1398
 
1399
1399
  ${response.authUrl}
@@ -1401,11 +1401,11 @@ ${response.authUrl}
1401
1401
  After approving access, Google returns to the Fluncle admin callback and stores the refresh token server-side.`);
1402
1402
  }
1403
1403
  async function initiate(mixtapeId, contentLength, contentType) {
1404
- const response = await adminApiPost(`/api/admin/mixtapes/${encodeURIComponent(mixtapeId)}/youtube/initiate`, { contentLength, contentType });
1404
+ const response = await adminApiPost(`/api/v1/admin/mixtapes/${encodeURIComponent(mixtapeId)}/youtube/initiate`, { contentLength, contentType });
1405
1405
  return { accessToken: response.accessToken, sessionUri: response.sessionUri };
1406
1406
  }
1407
1407
  async function mintToken() {
1408
- const response = await adminApiPost("/api/admin/youtube/token");
1408
+ const response = await adminApiPost("/api/v1/admin/youtube/token");
1409
1409
  return response.accessToken;
1410
1410
  }
1411
1411
  async function putChunk(args) {
@@ -1465,7 +1465,7 @@ function nextOffset(rangeHeader, fallback) {
1465
1465
  return Number(match[1]) + 1;
1466
1466
  }
1467
1467
  async function resolveMixtapeId(idOrLogId) {
1468
- const response = await adminApiGet("/api/admin/mixtapes");
1468
+ const response = await adminApiGet("/api/v1/admin/mixtapes");
1469
1469
  const match = response.mixtapes.find((mixtape) => mixtape.id === idOrLogId || mixtape.logId === idOrLogId);
1470
1470
  if (!match?.id) {
1471
1471
  throw new CliError2("mixtape_not_found", `No mixtape with id or Log ID ${idOrLogId}`);
@@ -1553,18 +1553,18 @@ async function distributeMixcloud(mixtapeId, audioPath, onProgress, unlisted = f
1553
1553
  const externalId = result.key;
1554
1554
  const url = `https://www.mixcloud.com${result.key}`;
1555
1555
  onProgress?.("Mixcloud: recording the link…");
1556
- await adminApiPost(`/api/admin/mixtapes/${encodeURIComponent(mixtapeId)}/mixcloud/finalize`, {
1556
+ await adminApiPost(`/api/v1/admin/mixtapes/${encodeURIComponent(mixtapeId)}/mixcloud/finalize`, {
1557
1557
  externalId,
1558
1558
  url
1559
1559
  });
1560
1560
  return { url };
1561
1561
  }
1562
1562
  async function resyncMixcloud(mixtapeId) {
1563
- const response = await adminApiPost(`/api/admin/mixtapes/${encodeURIComponent(mixtapeId)}/mixcloud/resync`);
1563
+ const response = await adminApiPost(`/api/v1/admin/mixtapes/${encodeURIComponent(mixtapeId)}/mixcloud/resync`);
1564
1564
  return { url: response.url };
1565
1565
  }
1566
1566
  async function authMixcloudCommand() {
1567
- const response = await adminApiGet("/api/admin/mixcloud/auth/start");
1567
+ const response = await adminApiGet("/api/v1/admin/mixcloud/auth/start");
1568
1568
  console.log(`Open this Mixcloud authorization URL:
1569
1569
 
1570
1570
  ${response.authUrl}
@@ -1591,7 +1591,7 @@ function mixtapeTags(_mixtape) {
1591
1591
  }
1592
1592
  async function fetchMixcloudToken() {
1593
1593
  try {
1594
- const response = await adminApiPost("/api/admin/mixcloud/token");
1594
+ const response = await adminApiPost("/api/v1/admin/mixcloud/token");
1595
1595
  return response.accessToken;
1596
1596
  } catch {
1597
1597
  throw new CliError2("mixcloud_not_connected", "Mixcloud is not connected. Run `fluncle admin auth mixcloud` to authorize it.");
@@ -1648,11 +1648,11 @@ __export(exports_mixtapes, {
1648
1648
  mixtapeDistributeCommand: () => mixtapeDistributeCommand
1649
1649
  });
1650
1650
  async function mixtapesCommand() {
1651
- const response = await publicApiGet("/api/mixtapes");
1651
+ const response = await publicApiGet("/api/v1/mixtapes");
1652
1652
  return response.mixtapes;
1653
1653
  }
1654
1654
  async function mixtapeUpdateCommand(id, options) {
1655
- return adminApiPatch(`/api/admin/mixtapes/${encodeURIComponent(id)}`, buildBody(options));
1655
+ return adminApiPatch(`/api/v1/admin/mixtapes/${encodeURIComponent(id)}`, buildBody(options));
1656
1656
  }
1657
1657
  async function mixtapeDistributeCommand(idOrLogId, options, onProgress = () => {}) {
1658
1658
  const mixtape = await mixtapeGetCommand(idOrLogId);
@@ -1723,7 +1723,7 @@ async function mixtapeResyncCommand(idOrLogId, options, onProgress = () => {}) {
1723
1723
  let doYoutube = Boolean(options.youtube);
1724
1724
  let doMixcloud = Boolean(options.mixcloud);
1725
1725
  if (!explicit) {
1726
- const social = await adminApiGet(`/api/admin/mixtapes/${encodeURIComponent(mixtapeId)}/social`);
1726
+ const social = await adminApiGet(`/api/v1/admin/mixtapes/${encodeURIComponent(mixtapeId)}/social`);
1727
1727
  const platforms = new Set(social.posts.map((post) => post.platform));
1728
1728
  doYoutube = platforms.has("youtube");
1729
1729
  doMixcloud = platforms.has("mixcloud");
@@ -1942,7 +1942,7 @@ async function recentCommand2(limit) {
1942
1942
  if (cursor) {
1943
1943
  params.set("cursor", cursor);
1944
1944
  }
1945
- const response = await publicApiGet(`/api/tracks?${params.toString()}`);
1945
+ const response = await publicApiGet(`/api/v1/findings?${params.toString()}`);
1946
1946
  for (const apiTrack of response.tracks) {
1947
1947
  results.push(mapTrack2(apiTrack));
1948
1948
  if (results.length >= limit) {
@@ -2031,7 +2031,7 @@ __export(exports_random, {
2031
2031
  randomCommand: () => randomCommand
2032
2032
  });
2033
2033
  async function randomCommand() {
2034
- const response = await publicApiGet("/api/tracks/random");
2034
+ const response = await publicApiGet("/api/v1/tracks/random");
2035
2035
  return response.track;
2036
2036
  }
2037
2037
  var init_random = __esm(() => {
@@ -2048,7 +2048,7 @@ async function subscribeCommand(email, json) {
2048
2048
  if (!address) {
2049
2049
  throw new CliError2("invalid_email", "Enter a valid email address.");
2050
2050
  }
2051
- await publicApiPost("/api/newsletter", {
2051
+ await publicApiPost("/api/v1/newsletter", {
2052
2052
  email: address
2053
2053
  });
2054
2054
  if (json) {
@@ -2076,7 +2076,7 @@ async function submitCommand(input) {
2076
2076
  if (!query) {
2077
2077
  throw new CliError2("missing_query", "Missing search input");
2078
2078
  }
2079
- const response = await publicApiGet(`/api/search?q=${encodeURIComponent(query)}`);
2079
+ const response = await publicApiGet(`/api/v1/search?q=${encodeURIComponent(query)}`);
2080
2080
  if (response.results.length === 0) {
2081
2081
  throw new CliError2("no_results", "No Spotify tracks found.");
2082
2082
  }
@@ -2086,7 +2086,7 @@ async function submitCommand(input) {
2086
2086
  }
2087
2087
  const note = await promptLine("Note (optional): ", PROMPT_NON_INTERACTIVE_MESSAGE2);
2088
2088
  const contact = await promptLine("Contact (optional): ", PROMPT_NON_INTERACTIVE_MESSAGE2);
2089
- await publicApiPost("/api/submissions", {
2089
+ await publicApiPost("/api/v1/submissions", {
2090
2090
  album: selected.album,
2091
2091
  artists: selected.artists,
2092
2092
  artworkUrl: selected.artworkUrl,
@@ -2229,7 +2229,7 @@ async function pollForToken(baseUrl, device) {
2229
2229
  throw new CliError2("expired_token", "The login request timed out. Run `fluncle login` again.");
2230
2230
  }
2231
2231
  async function fetchSessionUser(baseUrl, token) {
2232
- const response = await fetch(`${baseUrl}/api/me`, {
2232
+ const response = await fetch(`${baseUrl}/api/v1/me`, {
2233
2233
  headers: { Authorization: `Bearer ${token}` }
2234
2234
  });
2235
2235
  if (!response.ok) {
@@ -2264,8 +2264,8 @@ __export(exports_me, {
2264
2264
  });
2265
2265
  async function meCommand() {
2266
2266
  const [me, progress] = await Promise.all([
2267
- userApiGet("/api/me"),
2268
- userApiGet("/api/me/galaxy-progress")
2267
+ userApiGet("/api/v1/me"),
2268
+ userApiGet("/api/v1/me/galaxy-progress")
2269
2269
  ]);
2270
2270
  if (!me.user) {
2271
2271
  throw new Error("Your sign-in expired. Run `fluncle login` to link this device again.");
@@ -2442,7 +2442,7 @@ function parseVersion2(version) {
2442
2442
  var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
2443
2443
  var init_version2 = __esm(() => {
2444
2444
  init_output();
2445
- currentVersion2 = "0.186.0".trim() ? "0.186.0".trim() : "0.1.0";
2445
+ currentVersion2 = "0.187.0".trim() ? "0.187.0".trim() : "0.1.0";
2446
2446
  });
2447
2447
 
2448
2448
  // ../../packages/registry/src/index.ts
@@ -2761,7 +2761,22 @@ var init_src = __esm(() => {
2761
2761
  {
2762
2762
  apiFormat: "application/json",
2763
2763
  discoveryUrl: `${SITE}/api/v1/openapi.json`,
2764
- exposedContent: ["the archive as JSON, cursor-paginated (limit max 48, cursor)"],
2764
+ exposedContent: [
2765
+ "the feed as JSON — findings and published mixtapes, newest found first, cursor-paginated (limit max 48, cursor)"
2766
+ ],
2767
+ kind: "api",
2768
+ name: "api.findings",
2769
+ probeConfig: { cadenceMs: PROBE_CADENCE_MS, kind: "http", timeoutMs: PROBE_TIMEOUT_MS },
2770
+ route: "/api/v1/findings",
2771
+ url: `${SITE}/api/v1/findings`,
2772
+ weights: { status: "secondary", web: "primary" }
2773
+ },
2774
+ {
2775
+ apiFormat: "application/json",
2776
+ discoveryUrl: `${SITE}/api/v1/openapi.json`,
2777
+ exposedContent: [
2778
+ "every track Fluncle holds as JSON, newest release first, numbered pages (page); certified=true narrows to findings, certified=false to the rest, omitted returns both"
2779
+ ],
2765
2780
  kind: "api",
2766
2781
  name: "api.tracks",
2767
2782
  probeConfig: { cadenceMs: PROBE_CADENCE_MS, kind: "http", timeoutMs: PROBE_TIMEOUT_MS },
@@ -2940,8 +2955,8 @@ var init_src = __esm(() => {
2940
2955
  name: "api.health",
2941
2956
  operatorNotes: "Linked as the `status` relation from /.well-known/api-catalog. Service `web` on /status.",
2942
2957
  probeConfig: { cadenceMs: PROBE_CADENCE_MS, kind: "http", timeoutMs: PROBE_TIMEOUT_MS },
2943
- route: "/api/health",
2944
- url: `${SITE}/api/health`,
2958
+ route: "/api/v1/health",
2959
+ url: `${SITE}/api/v1/health`,
2945
2960
  weights: { status: "tertiary", web: "tertiary" }
2946
2961
  },
2947
2962
  {
@@ -3144,7 +3159,7 @@ var init_src = __esm(() => {
3144
3159
  apiFormat: "application/json",
3145
3160
  discoveryUrl: `${SITE}/.well-known/mcp/server-card.json`,
3146
3161
  exposedContent: [
3147
- "the archive as MCP tools (Streamable HTTP, no auth): list_tracks, list_fresh, get_track, get_random_track, get_status, search_archive, get_artist, get_label, build_set, get_similar_artists, list_album_catalogue, list_artist_catalogue, list_label_catalogue, search_tracks, submit_track, subscribe_newsletter",
3162
+ "the archive as MCP tools (Streamable HTTP, no auth): list_findings, list_tracks, list_fresh, get_track, get_random_track, get_status, search_archive, get_artist, get_label, build_set, list_similar_artists, list_album_catalogue, list_artist_catalogue, list_label_catalogue, search_tracks, submit_track, subscribe_newsletter",
3148
3163
  "the archive as MCP resources: each finding/mixtape at fluncle://finding/<logId> or fluncle://mixtape/<logId> (its public record)",
3149
3164
  "Fluncle-voiced MCP prompts: recommend_finding, walk_recent_night, decode_coordinate"
3150
3165
  ],
@@ -3896,7 +3911,7 @@ __export(exports_status, {
3896
3911
  statusCommand: () => statusCommand
3897
3912
  });
3898
3913
  async function statusCommand() {
3899
- return publicApiGet("/api/status");
3914
+ return publicApiGet("/api/v1/status");
3900
3915
  }
3901
3916
  function ago(seconds) {
3902
3917
  if (seconds < 60) {
@@ -3980,14 +3995,14 @@ __export(exports_track, {
3980
3995
  checkBundleCompleteness: () => checkBundleCompleteness
3981
3996
  });
3982
3997
  async function trackGetCommand(idOrLogId) {
3983
- return publicApiGet(`/api/tracks/${encodeURIComponent(idOrLogId)}`);
3998
+ return publicApiGet(`/api/v1/tracks/${encodeURIComponent(idOrLogId)}`);
3984
3999
  }
3985
4000
  async function trackSimilarCommand(idOrLogId, limit) {
3986
4001
  const query = limit === undefined ? "" : `?limit=${encodeURIComponent(String(limit))}`;
3987
- return publicApiGet(`/api/tracks/${encodeURIComponent(idOrLogId)}/similar${query}`);
4002
+ return publicApiGet(`/api/v1/tracks/${encodeURIComponent(idOrLogId)}/similar${query}`);
3988
4003
  }
3989
4004
  async function trackGetAdminCommand(idOrLogId) {
3990
- return adminApiGet(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}`);
4005
+ return adminApiGet(`/api/v1/admin/tracks/${encodeURIComponent(idOrLogId)}`);
3991
4006
  }
3992
4007
  function isPlatesOnlyUpload(files) {
3993
4008
  const hasPlate = PLATE_FIELDS.some((option) => Boolean(files[option]));
@@ -4034,7 +4049,7 @@ async function trackVideoCommand(idOrLogId, files, onProgress, options = {}) {
4034
4049
  throw new CliError2("nothing_to_upload", "No bundle files resolved to upload (pass --dir <bundle> or explicit file flags).");
4035
4050
  }
4036
4051
  const platesOnly = isPlatesOnlyUpload(files);
4037
- const presign = await adminApiPost(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/video/uploads`, { fields: present.map((spec) => spec.field) });
4052
+ const presign = await adminApiPost(`/api/v1/admin/tracks/${encodeURIComponent(idOrLogId)}/video/uploads`, { fields: present.map((spec) => spec.field) });
4038
4053
  const byField = new Map(presign.uploads.map((upload) => [upload.field, upload]));
4039
4054
  const urls = {};
4040
4055
  const STREAM_THRESHOLD_BYTES = 8 * 1024 * 1024;
@@ -4065,7 +4080,7 @@ async function trackVideoCommand(idOrLogId, files, onProgress, options = {}) {
4065
4080
  const videoModel = files.model?.trim().slice(0, 120) || manifest.model || DEFAULT_VIDEO_MODEL;
4066
4081
  const videoModelReasoning = files.reasoning?.trim().slice(0, 120) || manifest.reasoning || DEFAULT_VIDEO_REASONING;
4067
4082
  const squared = Boolean(urls["footage"] && urls["footage-social"]);
4068
- const finalize = await adminApiPost(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/video/finalize`, {
4083
+ const finalize = await adminApiPost(`/api/v1/admin/tracks/${encodeURIComponent(idOrLogId)}/video/finalize`, {
4069
4084
  videoModel,
4070
4085
  videoModelReasoning,
4071
4086
  ...squared ? { squared: true } : {},
@@ -4096,7 +4111,7 @@ async function readManifestFields(renderPath) {
4096
4111
  return result;
4097
4112
  }
4098
4113
  async function trackDraftCommand(idOrLogId, platform2) {
4099
- return adminApiPost(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/social/${platform2}/draft`);
4114
+ return adminApiPost(`/api/v1/admin/tracks/${encodeURIComponent(idOrLogId)}/social/${platform2}/draft`);
4100
4115
  }
4101
4116
  async function trackSocialUpdateCommand(idOrLogId, platform2, options) {
4102
4117
  const body = { status: options.status };
@@ -4106,14 +4121,14 @@ async function trackSocialUpdateCommand(idOrLogId, platform2, options) {
4106
4121
  if (options.scheduledFor !== undefined) {
4107
4122
  body.scheduledFor = options.scheduledFor;
4108
4123
  }
4109
- return adminApiPatch(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/social/${platform2}`, body);
4124
+ return adminApiPatch(`/api/v1/admin/tracks/${encodeURIComponent(idOrLogId)}/social/${platform2}`, body);
4110
4125
  }
4111
4126
  async function trackSocialShowCommand(idOrLogId) {
4112
- return adminApiGet(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/social`);
4127
+ return adminApiGet(`/api/v1/admin/tracks/${encodeURIComponent(idOrLogId)}/social`);
4113
4128
  }
4114
4129
  async function trackSocialCaptureCommand(limit) {
4115
4130
  const body = limit === undefined ? {} : { limit: String(limit) };
4116
- return adminApiPost(`/api/admin/social/posts/capture`, body);
4131
+ return adminApiPost(`/api/v1/admin/social/posts/capture`, body);
4117
4132
  }
4118
4133
  async function trackUpdateCommand(trackId, options) {
4119
4134
  const body = {};
@@ -4159,13 +4174,13 @@ async function trackUpdateCommand(trackId, options) {
4159
4174
  if (options.analyzedAt !== undefined) {
4160
4175
  body.analyzedAt = options.analyzedAt;
4161
4176
  }
4162
- return adminApiPatch(`/api/admin/tracks/${encodeURIComponent(trackId)}`, body);
4177
+ return adminApiPatch(`/api/v1/admin/tracks/${encodeURIComponent(trackId)}`, body);
4163
4178
  }
4164
4179
  async function trackRequeueVideoCommand(idOrLogId) {
4165
- return adminApiPost(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/video/requeue`);
4180
+ return adminApiPost(`/api/v1/admin/tracks/${encodeURIComponent(idOrLogId)}/video/requeue`);
4166
4181
  }
4167
4182
  async function trackPurgeVideoCommand(idOrLogId) {
4168
- return adminApiPost(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/video/purge`);
4183
+ return adminApiPost(`/api/v1/admin/tracks/${encodeURIComponent(idOrLogId)}/video/purge`);
4169
4184
  }
4170
4185
  async function trackObserveCommand(idOrLogId, options) {
4171
4186
  const body = { script: options.script };
@@ -4187,7 +4202,7 @@ async function trackObserveCommand(idOrLogId, options) {
4187
4202
  if (options.force) {
4188
4203
  body.force = true;
4189
4204
  }
4190
- return adminApiPost(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/observe`, body);
4205
+ return adminApiPost(`/api/v1/admin/tracks/${encodeURIComponent(idOrLogId)}/observe`, body);
4191
4206
  }
4192
4207
  async function trackContextCommand(idOrLogId, options = {}) {
4193
4208
  const body = {};
@@ -4197,7 +4212,7 @@ async function trackContextCommand(idOrLogId, options = {}) {
4197
4212
  if (options.refresh) {
4198
4213
  body.refresh = true;
4199
4214
  }
4200
- return adminApiPost(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/context`, body);
4215
+ return adminApiPost(`/api/v1/admin/tracks/${encodeURIComponent(idOrLogId)}/context`, body);
4201
4216
  }
4202
4217
  async function trackNoteCommand(idOrLogId, options) {
4203
4218
  const body = { note: options.note };
@@ -4207,7 +4222,7 @@ async function trackNoteCommand(idOrLogId, options) {
4207
4222
  if (typeof options.promptVersion === "number") {
4208
4223
  body.promptVersion = options.promptVersion;
4209
4224
  }
4210
- return adminApiPost(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/note`, body);
4225
+ return adminApiPost(`/api/v1/admin/tracks/${encodeURIComponent(idOrLogId)}/note`, body);
4211
4226
  }
4212
4227
  var DEFAULT_VIDEO_MODEL = "anthropic/claude-opus-4-8", DEFAULT_VIDEO_REASONING = "high", FOUND_BASE = "https://found.fluncle.com", VIDEO_FIELDS, RERENDER_CONTRACT_FIELDS, RERENDER_ADVISORY_FIELDS, FOOTAGE_FIELDS, PLATE_FIELDS, NON_FILE_OPTIONS, DIVERSITY_LEDGER_FIELDS;
4213
4228
  var init_track = __esm(() => {
@@ -4260,7 +4275,7 @@ __export(exports_admin_attention, {
4260
4275
  attentionQueueCommand: () => attentionQueueCommand
4261
4276
  });
4262
4277
  async function attentionQueueCommand() {
4263
- const response = await adminApiGet("/api/admin/attention");
4278
+ const response = await adminApiGet("/api/v1/admin/attention");
4264
4279
  return response.attention;
4265
4280
  }
4266
4281
  function attentionQueueLines(queue) {
@@ -4304,7 +4319,7 @@ __export(exports_add, {
4304
4319
  addCommand: () => addCommand
4305
4320
  });
4306
4321
  async function addCommand(spotifyUrl, options) {
4307
- const result = await adminApiPost("/api/admin/tracks", {
4322
+ const result = await adminApiPost("/api/v1/admin/tracks", {
4308
4323
  dryRun: options.dryRun,
4309
4324
  note: options.note,
4310
4325
  spotifyUrl
@@ -4369,7 +4384,7 @@ async function trackUpdateCommand2(trackId, options) {
4369
4384
  if (options.analyzedAt !== undefined) {
4370
4385
  body.analyzedAt = options.analyzedAt;
4371
4386
  }
4372
- return adminApiPatch(`/api/admin/tracks/${encodeURIComponent(trackId)}`, body);
4387
+ return adminApiPatch(`/api/v1/admin/tracks/${encodeURIComponent(trackId)}`, body);
4373
4388
  }
4374
4389
  var init_track2 = __esm(() => {
4375
4390
  init_api();
@@ -4447,7 +4462,7 @@ async function fetchAdminTracks(options) {
4447
4462
  if (cursor) {
4448
4463
  params.set("cursor", cursor);
4449
4464
  }
4450
- const response = await adminApiGet(`/api/admin/tracks?${params.toString()}`);
4465
+ const response = await adminApiGet(`/api/v1/admin/tracks?${params.toString()}`);
4451
4466
  for (const apiTrack of response.tracks) {
4452
4467
  const track = mapTrack2(apiTrack);
4453
4468
  if (track.type === "mixtape") {
@@ -4496,7 +4511,7 @@ async function trackWorkCommand(options) {
4496
4511
  if (options.count) {
4497
4512
  params.set("count", "true");
4498
4513
  }
4499
- const response = await adminApiGet(`/api/admin/tracks/work?${params.toString()}`);
4514
+ const response = await adminApiGet(`/api/v1/admin/tracks/work?${params.toString()}`);
4500
4515
  return { queued: response.queued, tracks: response.tracks ?? [] };
4501
4516
  }
4502
4517
  async function requeueAnalysisCommand(options) {
@@ -4561,46 +4576,46 @@ async function backfillLastfmCommand(limit, dryRun, cursor) {
4561
4576
  if (cursor) {
4562
4577
  params.set("cursor", cursor);
4563
4578
  }
4564
- return adminApiPost(`/api/admin/backfill/lastfm?${params.toString()}`);
4579
+ return adminApiPost(`/api/v1/admin/backfill/lastfm?${params.toString()}`);
4565
4580
  }
4566
4581
  async function backfillDiscogsCommand(limit, dryRun, cursor) {
4567
4582
  const params = new URLSearchParams({ dryRun: String(dryRun), limit: String(limit) });
4568
4583
  if (cursor) {
4569
4584
  params.set("cursor", cursor);
4570
4585
  }
4571
- return adminApiPost(`/api/admin/backfill/discogs?${params.toString()}`);
4586
+ return adminApiPost(`/api/v1/admin/backfill/discogs?${params.toString()}`);
4572
4587
  }
4573
4588
  async function backfillAppleMusicCommand(limit, dryRun, cursor) {
4574
4589
  const params = new URLSearchParams({ dryRun: String(dryRun), limit: String(limit) });
4575
4590
  if (cursor) {
4576
4591
  params.set("cursor", cursor);
4577
4592
  }
4578
- return adminApiPost(`/api/admin/backfill/apple-music?${params.toString()}`);
4593
+ return adminApiPost(`/api/v1/admin/backfill/apple-music?${params.toString()}`);
4579
4594
  }
4580
4595
  async function backfillAppleCatalogueCommand(limit, dryRun) {
4581
4596
  const params = new URLSearchParams({ dryRun: String(dryRun), limit: String(limit) });
4582
- return adminApiPost(`/api/admin/backfill/apple-catalogue?${params.toString()}`);
4597
+ return adminApiPost(`/api/v1/admin/backfill/apple-catalogue?${params.toString()}`);
4583
4598
  }
4584
4599
  async function backfillRecordingMbidsCommand(limit, dryRun, cursor) {
4585
4600
  const params = new URLSearchParams({ dryRun: String(dryRun), limit: String(limit) });
4586
4601
  if (cursor) {
4587
4602
  params.set("cursor", cursor);
4588
4603
  }
4589
- return adminApiPost(`/api/admin/backfill/recording-mbids?${params.toString()}`);
4604
+ return adminApiPost(`/api/v1/admin/backfill/recording-mbids?${params.toString()}`);
4590
4605
  }
4591
4606
  async function backfillArtistEdgesCommand(limit, dryRun, cursor) {
4592
4607
  const params = new URLSearchParams({ dryRun: String(dryRun), limit: String(limit) });
4593
4608
  if (cursor) {
4594
4609
  params.set("cursor", cursor);
4595
4610
  }
4596
- return adminApiPost(`/api/admin/backfill/artist-edges?${params.toString()}`);
4611
+ return adminApiPost(`/api/v1/admin/backfill/artist-edges?${params.toString()}`);
4597
4612
  }
4598
4613
  async function backfillArtistCreditsCommand(limit, dryRun, cursor) {
4599
4614
  const params = new URLSearchParams({ dryRun: String(dryRun), limit: String(limit) });
4600
4615
  if (cursor) {
4601
4616
  params.set("cursor", cursor);
4602
4617
  }
4603
- return adminApiPost(`/api/admin/backfill/artist-credits?${params.toString()}`);
4618
+ return adminApiPost(`/api/v1/admin/backfill/artist-credits?${params.toString()}`);
4604
4619
  }
4605
4620
  async function vehiclesCommand(limit) {
4606
4621
  const tracks = await fetchAdminTracks({ hasVideo: true, max: limit, order: "desc" });
@@ -4620,7 +4635,7 @@ async function mixableOrderCommand(logIds, seed) {
4620
4635
  if (seed) {
4621
4636
  params.set("seed", seed);
4622
4637
  }
4623
- return adminApiGet(`/api/admin/tracks/mixable-order?${params.toString()}`);
4638
+ return adminApiGet(`/api/v1/admin/tracks/mixable-order?${params.toString()}`);
4624
4639
  }
4625
4640
  var pageSize3 = 48;
4626
4641
  var init_admin_tracks = __esm(() => {
@@ -4641,7 +4656,7 @@ async function previewArchiveUploadCommand(idOrLogId, options) {
4641
4656
  form.append("preview", Bun.file(options.file), basename(options.file));
4642
4657
  form.append("source", options.source);
4643
4658
  form.append("mime", options.mime);
4644
- return adminApiPostForm(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/preview`, form);
4659
+ return adminApiPostForm(`/api/v1/admin/tracks/${encodeURIComponent(idOrLogId)}/preview`, form);
4645
4660
  }
4646
4661
  async function previewArchiveBackfillCommand(options) {
4647
4662
  const result = {
@@ -4652,7 +4667,7 @@ async function previewArchiveBackfillCommand(options) {
4652
4667
  };
4653
4668
  let cursor;
4654
4669
  while (result.archived.length < (options.limit ?? Number.POSITIVE_INFINITY)) {
4655
- const page = await publicApiGet(`/api/tracks?limit=48${cursor ? `&cursor=${encodeURIComponent(cursor)}` : ""}`);
4670
+ const page = await publicApiGet(`/api/v1/findings?limit=48${cursor ? `&cursor=${encodeURIComponent(cursor)}` : ""}`);
4656
4671
  for (const track of page.tracks) {
4657
4672
  if (result.archived.length >= (options.limit ?? Number.POSITIVE_INFINITY)) {
4658
4673
  break;
@@ -4664,7 +4679,7 @@ async function previewArchiveBackfillCommand(options) {
4664
4679
  result.skipped.push({ reason: "no_log_id", trackId: track.trackId });
4665
4680
  continue;
4666
4681
  }
4667
- const status = await adminApiGet(`/api/admin/tracks/${encodeURIComponent(track.trackId)}/preview`);
4682
+ const status = await adminApiGet(`/api/v1/admin/tracks/${encodeURIComponent(track.trackId)}/preview`);
4668
4683
  if (status.archived) {
4669
4684
  result.skipped.push({ reason: "already_archived", trackId: track.trackId });
4670
4685
  continue;
@@ -4703,7 +4718,7 @@ async function uploadResolvedPreview(trackId, preview) {
4703
4718
  form.append("preview", new Blob([preview.bytes], { type: preview.mime }), `preview.${extension}`);
4704
4719
  form.append("source", preview.source);
4705
4720
  form.append("mime", preview.mime);
4706
- await adminApiPostForm(`/api/admin/tracks/${encodeURIComponent(trackId)}/preview`, form);
4721
+ await adminApiPostForm(`/api/v1/admin/tracks/${encodeURIComponent(trackId)}/preview`, form);
4707
4722
  }
4708
4723
  async function resolvePreview(track) {
4709
4724
  const stored = await downloadPreview(track.previewUrl, "deezer:stored");
@@ -4883,20 +4898,20 @@ async function distributeYoutube2(mixtapeId, videoPath, onProgress) {
4883
4898
  offset = 0;
4884
4899
  }
4885
4900
  onProgress?.("Recording the YouTube link");
4886
- await adminApiPost(`/api/admin/mixtapes/${encodeURIComponent(mixtapeId)}/youtube/finalize`, { videoId });
4901
+ await adminApiPost(`/api/v1/admin/mixtapes/${encodeURIComponent(mixtapeId)}/youtube/finalize`, { videoId });
4887
4902
  return { url: `https://youtu.be/${videoId}`, videoId };
4888
4903
  }
4889
4904
  async function publishYoutubeCommand2(idOrLogId) {
4890
4905
  const mixtapeId = await resolveMixtapeId2(idOrLogId);
4891
- const response = await adminApiPost(`/api/admin/mixtapes/${encodeURIComponent(mixtapeId)}/youtube/publish`);
4906
+ const response = await adminApiPost(`/api/v1/admin/mixtapes/${encodeURIComponent(mixtapeId)}/youtube/publish`);
4892
4907
  return { url: response.url };
4893
4908
  }
4894
4909
  async function resyncYoutube2(mixtapeId) {
4895
- const response = await adminApiPost(`/api/admin/mixtapes/${encodeURIComponent(mixtapeId)}/youtube/resync`);
4910
+ const response = await adminApiPost(`/api/v1/admin/mixtapes/${encodeURIComponent(mixtapeId)}/youtube/resync`);
4896
4911
  return { url: response.url, videoId: response.videoId };
4897
4912
  }
4898
4913
  async function authYoutubeCommand2() {
4899
- const response = await adminApiGet("/api/admin/youtube/auth/start");
4914
+ const response = await adminApiGet("/api/v1/admin/youtube/auth/start");
4900
4915
  console.log(`Open this YouTube authorization URL:
4901
4916
 
4902
4917
  ${response.authUrl}
@@ -4904,11 +4919,11 @@ ${response.authUrl}
4904
4919
  After approving access, Google returns to the Fluncle admin callback and stores the refresh token server-side.`);
4905
4920
  }
4906
4921
  async function initiate2(mixtapeId, contentLength, contentType) {
4907
- const response = await adminApiPost(`/api/admin/mixtapes/${encodeURIComponent(mixtapeId)}/youtube/initiate`, { contentLength, contentType });
4922
+ const response = await adminApiPost(`/api/v1/admin/mixtapes/${encodeURIComponent(mixtapeId)}/youtube/initiate`, { contentLength, contentType });
4908
4923
  return { accessToken: response.accessToken, sessionUri: response.sessionUri };
4909
4924
  }
4910
4925
  async function mintToken2() {
4911
- const response = await adminApiPost("/api/admin/youtube/token");
4926
+ const response = await adminApiPost("/api/v1/admin/youtube/token");
4912
4927
  return response.accessToken;
4913
4928
  }
4914
4929
  async function putChunk2(args) {
@@ -4968,7 +4983,7 @@ function nextOffset2(rangeHeader, fallback) {
4968
4983
  return Number(match[1]) + 1;
4969
4984
  }
4970
4985
  async function resolveMixtapeId2(idOrLogId) {
4971
- const response = await adminApiGet("/api/admin/mixtapes");
4986
+ const response = await adminApiGet("/api/v1/admin/mixtapes");
4972
4987
  const match = response.mixtapes.find((mixtape) => mixtape.id === idOrLogId || mixtape.logId === idOrLogId);
4973
4988
  if (!match?.id) {
4974
4989
  throw new CliError2("mixtape_not_found", `No mixtape with id or Log ID ${idOrLogId}`);
@@ -5004,10 +5019,10 @@ __export(exports_publish, {
5004
5019
  publishAdvanceCommand: () => publishAdvanceCommand
5005
5020
  });
5006
5021
  async function publishAdvanceCommand() {
5007
- return adminApiPost("/api/admin/social/publish/advance", {});
5022
+ return adminApiPost("/api/v1/admin/social/publish/advance", {});
5008
5023
  }
5009
5024
  async function publishAdvancePauseCommand(paused) {
5010
- const response = await adminApiPut("/api/admin/social/publish/advance/state", { paused });
5025
+ const response = await adminApiPut("/api/v1/admin/social/publish/advance/state", { paused });
5011
5026
  return response.paused;
5012
5027
  }
5013
5028
  var init_publish = __esm(() => {
@@ -5021,10 +5036,10 @@ __export(exports_capture, {
5021
5036
  captureBudgetCommand: () => captureBudgetCommand
5022
5037
  });
5023
5038
  async function captureBudgetCommand() {
5024
- return adminApiGet("/api/admin/catalogue/capture-budget");
5039
+ return adminApiGet("/api/v1/admin/catalogue/capture-budget");
5025
5040
  }
5026
5041
  async function setCaptureBudgetCommand(input) {
5027
- return adminApiPut("/api/admin/catalogue/capture-budget", input);
5042
+ return adminApiPut("/api/v1/admin/catalogue/capture-budget", input);
5028
5043
  }
5029
5044
  var init_capture = __esm(() => {
5030
5045
  init_api();
@@ -5228,7 +5243,7 @@ __export(exports_recordings, {
5228
5243
  });
5229
5244
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
5230
5245
  async function recordingGet(id) {
5231
- const response = await adminApiGet(`/api/admin/recordings/${encodeURIComponent(id)}`);
5246
+ const response = await adminApiGet(`/api/v1/admin/recordings/${encodeURIComponent(id)}`);
5232
5247
  return response.recording;
5233
5248
  }
5234
5249
  function formatRecordingSummary(recording) {
@@ -5246,7 +5261,7 @@ async function recordingsListCommand(options = {}) {
5246
5261
  query.set("parentId", options.parentId);
5247
5262
  }
5248
5263
  const suffix = query.toString() ? `?${query.toString()}` : "";
5249
- const response = await adminApiGet(`/api/admin/recordings${suffix}`);
5264
+ const response = await adminApiGet(`/api/v1/admin/recordings${suffix}`);
5250
5265
  if (options.json) {
5251
5266
  printJson2({ ok: true, recordings: response.recordings });
5252
5267
  return;
@@ -5276,7 +5291,7 @@ async function recordingGetCommand(id, options = {}) {
5276
5291
  }
5277
5292
  async function recordingCreateCommand(options = {}) {
5278
5293
  if (options.plan) {
5279
- const created2 = await adminApiPost("/api/admin/recordings", {
5294
+ const created2 = await adminApiPost("/api/v1/admin/recordings", {
5280
5295
  kind: "plan",
5281
5296
  recordedAt: options.recordedAt
5282
5297
  });
@@ -5298,7 +5313,7 @@ async function recordingCreateCommand(options = {}) {
5298
5313
  if (!existsSync2(options.video)) {
5299
5314
  throw new CliError2("file_not_found", `Set-video master not found: ${options.video}`);
5300
5315
  }
5301
- const created = await adminApiPost("/api/admin/recordings", {
5316
+ const created = await adminApiPost("/api/v1/admin/recordings", {
5302
5317
  recordedAt: options.recordedAt,
5303
5318
  title
5304
5319
  });
@@ -5309,7 +5324,7 @@ async function recordingCreateCommand(options = {}) {
5309
5324
  }
5310
5325
  };
5311
5326
  log(`Recording ${recording.id} created, staging the set video…`);
5312
- const upload = await uploadRenditionMultipart(options.video, `/api/admin/recordings/${encodeURIComponent(recording.id)}/set-video/presign`, log);
5327
+ const upload = await uploadRenditionMultipart(options.video, `/api/v1/admin/recordings/${encodeURIComponent(recording.id)}/set-video/presign`, log);
5313
5328
  if (options.json) {
5314
5329
  printJson2({ key: upload.key, ok: true, recording, url: upload.url });
5315
5330
  return;
@@ -5343,7 +5358,7 @@ async function recordingUpdateCommand(id, options = {}) {
5343
5358
  if (Object.keys(body).length === 0) {
5344
5359
  throw new CliError2("no_fields", "Nothing to update. Pass --title, --recorded-at, --parent-id, or --tracklist-file");
5345
5360
  }
5346
- const response = await adminApiPatch(`/api/admin/recordings/${encodeURIComponent(id)}`, body);
5361
+ const response = await adminApiPatch(`/api/v1/admin/recordings/${encodeURIComponent(id)}`, body);
5347
5362
  if (options.json) {
5348
5363
  printJson2({ ok: true, recording: response.recording });
5349
5364
  return;
@@ -5354,7 +5369,7 @@ async function recordingDeleteCommand(id, options = {}) {
5354
5369
  if (!id) {
5355
5370
  throw new CliError2("missing_id", "Missing recording id for: delete");
5356
5371
  }
5357
- await adminApiDelete(`/api/admin/recordings/${encodeURIComponent(id)}`);
5372
+ await adminApiDelete(`/api/v1/admin/recordings/${encodeURIComponent(id)}`);
5358
5373
  if (options.json) {
5359
5374
  printJson2({ ok: true });
5360
5375
  return;
@@ -5365,7 +5380,7 @@ async function recordingPromoteCommand(id, options = {}) {
5365
5380
  if (!id) {
5366
5381
  throw new CliError2("missing_id", "Missing recording id for: promote");
5367
5382
  }
5368
- const response = await adminApiPost(`/api/admin/recordings/${encodeURIComponent(id)}/promote`);
5383
+ const response = await adminApiPost(`/api/v1/admin/recordings/${encodeURIComponent(id)}/promote`);
5369
5384
  const recording = response.recording;
5370
5385
  if (options.json) {
5371
5386
  printJson2({ ok: true, recording });
@@ -5389,7 +5404,7 @@ async function recordingReplaceCuesCommand(id, options = {}) {
5389
5404
  } catch {
5390
5405
  throw new CliError2("invalid_cues", `Cues file is not valid JSON: ${options.cuesFile}`);
5391
5406
  }
5392
- const response = await adminApiPut(`/api/admin/recordings/${encodeURIComponent(id)}/cues`, { cues });
5407
+ const response = await adminApiPut(`/api/v1/admin/recordings/${encodeURIComponent(id)}/cues`, { cues });
5393
5408
  if (options.json) {
5394
5409
  printJson2({ ok: true, recording: response.recording });
5395
5410
  return;
@@ -5484,19 +5499,19 @@ async function clipsListCommand(filter = {}) {
5484
5499
  params.set("status", filter.status);
5485
5500
  }
5486
5501
  const query = params.toString();
5487
- const response = await adminApiGet(`/api/admin/clips${query ? `?${query}` : ""}`);
5502
+ const response = await adminApiGet(`/api/v1/admin/clips${query ? `?${query}` : ""}`);
5488
5503
  return response.clips;
5489
5504
  }
5490
5505
  async function clipPostsListCommand() {
5491
- const response = await adminApiGet("/api/admin/clips/social");
5506
+ const response = await adminApiGet("/api/v1/admin/clips/social");
5492
5507
  return response.posts;
5493
5508
  }
5494
5509
  async function clipScheduleCommand(clipId, scheduledFor) {
5495
- const response = await adminApiPatch(`/api/admin/clips/${encodeURIComponent(clipId)}/schedule`, { scheduledFor });
5510
+ const response = await adminApiPatch(`/api/v1/admin/clips/${encodeURIComponent(clipId)}/schedule`, { scheduledFor });
5496
5511
  return response.post;
5497
5512
  }
5498
5513
  async function clipDripPauseCommand(paused) {
5499
- const response = await adminApiPut("/api/admin/clips/drip/state", {
5514
+ const response = await adminApiPut("/api/v1/admin/clips/drip/state", {
5500
5515
  paused
5501
5516
  });
5502
5517
  return response.paused;
@@ -5537,9 +5552,9 @@ async function clipCutCommand(clipId, onProgress = () => {}) {
5537
5552
  throw new CliError2("clip_too_large", `The cut is ${(sizeBytes / 1e6).toFixed(1)} MB (> 100 MB Cloudflare MT ceiling). Shorten the window or lower the bitrate cap`);
5538
5553
  }
5539
5554
  onProgress(`Clip ${clipId}: uploading ${(sizeBytes / 1e6).toFixed(1)} MB…`);
5540
- const presign = await adminApiPost(`/api/admin/clips/${encodeURIComponent(clipId)}/cut/presign`, { contentType: "video/mp4" });
5555
+ const presign = await adminApiPost(`/api/v1/admin/clips/${encodeURIComponent(clipId)}/cut/presign`, { contentType: "video/mp4" });
5541
5556
  await putClip(presign.url, presign.contentType, outputPath);
5542
- await adminApiPost(`/api/admin/clips/${encodeURIComponent(clipId)}/cut/finalize`);
5557
+ await adminApiPost(`/api/v1/admin/clips/${encodeURIComponent(clipId)}/cut/finalize`);
5543
5558
  onProgress(`Clip ${clipId}: done → ${FOUND_BASE3}/${presign.key}`);
5544
5559
  return {
5545
5560
  clipId,
@@ -5609,7 +5624,7 @@ __export(exports_recordings2, {
5609
5624
  });
5610
5625
  import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
5611
5626
  async function recordingGet2(id) {
5612
- const response = await adminApiGet(`/api/admin/recordings/${encodeURIComponent(id)}`);
5627
+ const response = await adminApiGet(`/api/v1/admin/recordings/${encodeURIComponent(id)}`);
5613
5628
  return response.recording;
5614
5629
  }
5615
5630
  function formatRecordingSummary2(recording) {
@@ -5627,7 +5642,7 @@ async function recordingsListCommand2(options = {}) {
5627
5642
  query.set("parentId", options.parentId);
5628
5643
  }
5629
5644
  const suffix = query.toString() ? `?${query.toString()}` : "";
5630
- const response = await adminApiGet(`/api/admin/recordings${suffix}`);
5645
+ const response = await adminApiGet(`/api/v1/admin/recordings${suffix}`);
5631
5646
  if (options.json) {
5632
5647
  printJson2({ ok: true, recordings: response.recordings });
5633
5648
  return;
@@ -5657,7 +5672,7 @@ async function recordingGetCommand2(id, options = {}) {
5657
5672
  }
5658
5673
  async function recordingCreateCommand2(options = {}) {
5659
5674
  if (options.plan) {
5660
- const created2 = await adminApiPost("/api/admin/recordings", {
5675
+ const created2 = await adminApiPost("/api/v1/admin/recordings", {
5661
5676
  kind: "plan",
5662
5677
  recordedAt: options.recordedAt
5663
5678
  });
@@ -5679,7 +5694,7 @@ async function recordingCreateCommand2(options = {}) {
5679
5694
  if (!existsSync3(options.video)) {
5680
5695
  throw new CliError2("file_not_found", `Set-video master not found: ${options.video}`);
5681
5696
  }
5682
- const created = await adminApiPost("/api/admin/recordings", {
5697
+ const created = await adminApiPost("/api/v1/admin/recordings", {
5683
5698
  recordedAt: options.recordedAt,
5684
5699
  title
5685
5700
  });
@@ -5690,7 +5705,7 @@ async function recordingCreateCommand2(options = {}) {
5690
5705
  }
5691
5706
  };
5692
5707
  log(`Recording ${recording.id} created, staging the set video…`);
5693
- const upload = await uploadRenditionMultipart(options.video, `/api/admin/recordings/${encodeURIComponent(recording.id)}/set-video/presign`, log);
5708
+ const upload = await uploadRenditionMultipart(options.video, `/api/v1/admin/recordings/${encodeURIComponent(recording.id)}/set-video/presign`, log);
5694
5709
  if (options.json) {
5695
5710
  printJson2({ key: upload.key, ok: true, recording, url: upload.url });
5696
5711
  return;
@@ -5724,7 +5739,7 @@ async function recordingUpdateCommand2(id, options = {}) {
5724
5739
  if (Object.keys(body).length === 0) {
5725
5740
  throw new CliError2("no_fields", "Nothing to update. Pass --title, --recorded-at, --parent-id, or --tracklist-file");
5726
5741
  }
5727
- const response = await adminApiPatch(`/api/admin/recordings/${encodeURIComponent(id)}`, body);
5742
+ const response = await adminApiPatch(`/api/v1/admin/recordings/${encodeURIComponent(id)}`, body);
5728
5743
  if (options.json) {
5729
5744
  printJson2({ ok: true, recording: response.recording });
5730
5745
  return;
@@ -5735,7 +5750,7 @@ async function recordingDeleteCommand2(id, options = {}) {
5735
5750
  if (!id) {
5736
5751
  throw new CliError2("missing_id", "Missing recording id for: delete");
5737
5752
  }
5738
- await adminApiDelete(`/api/admin/recordings/${encodeURIComponent(id)}`);
5753
+ await adminApiDelete(`/api/v1/admin/recordings/${encodeURIComponent(id)}`);
5739
5754
  if (options.json) {
5740
5755
  printJson2({ ok: true });
5741
5756
  return;
@@ -5746,7 +5761,7 @@ async function recordingPromoteCommand2(id, options = {}) {
5746
5761
  if (!id) {
5747
5762
  throw new CliError2("missing_id", "Missing recording id for: promote");
5748
5763
  }
5749
- const response = await adminApiPost(`/api/admin/recordings/${encodeURIComponent(id)}/promote`);
5764
+ const response = await adminApiPost(`/api/v1/admin/recordings/${encodeURIComponent(id)}/promote`);
5750
5765
  const recording = response.recording;
5751
5766
  if (options.json) {
5752
5767
  printJson2({ ok: true, recording });
@@ -5770,7 +5785,7 @@ async function recordingReplaceCuesCommand2(id, options = {}) {
5770
5785
  } catch {
5771
5786
  throw new CliError2("invalid_cues", `Cues file is not valid JSON: ${options.cuesFile}`);
5772
5787
  }
5773
- const response = await adminApiPut(`/api/admin/recordings/${encodeURIComponent(id)}/cues`, { cues });
5788
+ const response = await adminApiPut(`/api/v1/admin/recordings/${encodeURIComponent(id)}/cues`, { cues });
5774
5789
  if (options.json) {
5775
5790
  printJson2({ ok: true, recording: response.recording });
5776
5791
  return;
@@ -5826,20 +5841,20 @@ function readContentFile(filePath) {
5826
5841
  }
5827
5842
  }
5828
5843
  async function newsletterDraftCommand(options) {
5829
- return adminApiPost("/api/admin/newsletter/editions", buildBody2(options, { requireContent: true }));
5844
+ return adminApiPost("/api/v1/admin/newsletter/editions", buildBody2(options, { requireContent: true }));
5830
5845
  }
5831
5846
  async function newsletterUpdateCommand(id, options) {
5832
- return adminApiPatch(`/api/admin/newsletter/editions/${encodeURIComponent(id)}`, buildBody2(options, { requireContent: false }));
5847
+ return adminApiPatch(`/api/v1/admin/newsletter/editions/${encodeURIComponent(id)}`, buildBody2(options, { requireContent: false }));
5833
5848
  }
5834
5849
  async function newsletterSendCommand(id) {
5835
- return adminApiPost(`/api/admin/newsletter/editions/${encodeURIComponent(id)}/send`);
5850
+ return adminApiPost(`/api/v1/admin/newsletter/editions/${encodeURIComponent(id)}/send`);
5836
5851
  }
5837
5852
  async function newsletterListCommand() {
5838
- const response = await adminApiGet("/api/admin/newsletter/editions");
5853
+ const response = await adminApiGet("/api/v1/admin/newsletter/editions");
5839
5854
  return response.editions;
5840
5855
  }
5841
5856
  async function newsletterDeleteCommand(id) {
5842
- return adminApiDelete(`/api/admin/newsletter/editions/${encodeURIComponent(id)}`);
5857
+ return adminApiDelete(`/api/v1/admin/newsletter/editions/${encodeURIComponent(id)}`);
5843
5858
  }
5844
5859
  var init_newsletter = __esm(() => {
5845
5860
  init_api();
@@ -5856,7 +5871,7 @@ __export(exports_admin_logbook, {
5856
5871
  import { existsSync as existsSync5, readFileSync as readFileSync5 } from "node:fs";
5857
5872
  async function logbookGapsCommand(limit) {
5858
5873
  const query = typeof limit === "number" ? `?limit=${encodeURIComponent(String(limit))}` : "";
5859
- const response = await adminApiGet(`/api/admin/logbook/gaps${query}`);
5874
+ const response = await adminApiGet(`/api/v1/admin/logbook/gaps${query}`);
5860
5875
  return { gaps: response.gaps, spent: response.spent };
5861
5876
  }
5862
5877
  function resolveBody(options) {
@@ -5878,14 +5893,14 @@ function requireTitle(options) {
5878
5893
  return options.title;
5879
5894
  }
5880
5895
  async function logbookCreateCommand(sector, options) {
5881
- return adminApiPost(`/api/admin/logbook/${encodeURIComponent(sector)}`, {
5896
+ return adminApiPost(`/api/v1/admin/logbook/${encodeURIComponent(sector)}`, {
5882
5897
  body: resolveBody(options),
5883
5898
  ...typeof options.promptVersion === "number" ? { promptVersion: options.promptVersion } : {},
5884
5899
  title: requireTitle(options)
5885
5900
  });
5886
5901
  }
5887
5902
  async function logbookUpdateCommand(sector, options) {
5888
- return adminApiPatch(`/api/admin/logbook/${encodeURIComponent(sector)}`, {
5903
+ return adminApiPatch(`/api/v1/admin/logbook/${encodeURIComponent(sector)}`, {
5889
5904
  body: resolveBody(options),
5890
5905
  title: requireTitle(options)
5891
5906
  });
@@ -5915,11 +5930,11 @@ __export(exports_admin_prompts, {
5915
5930
  });
5916
5931
  import { existsSync as existsSync6, readFileSync as readFileSync6 } from "node:fs";
5917
5932
  async function promptsListCommand() {
5918
- const response = await adminApiGet("/api/admin/prompts");
5933
+ const response = await adminApiGet("/api/v1/admin/prompts");
5919
5934
  return response.prompts;
5920
5935
  }
5921
5936
  async function promptGetCommand(slug) {
5922
- return adminApiGet(`/api/admin/prompts/${encodeURIComponent(slug)}`);
5937
+ return adminApiGet(`/api/v1/admin/prompts/${encodeURIComponent(slug)}`);
5923
5938
  }
5924
5939
  async function promptDetailCommand(slug) {
5925
5940
  const prompts = await promptsListCommand();
@@ -5945,7 +5960,7 @@ function resolveBody2(options) {
5945
5960
  async function promptUpdateCommand(slug, options) {
5946
5961
  const body = resolveBody2(options);
5947
5962
  const note = options.note?.trim();
5948
- const response = await adminApiPost(`/api/admin/prompts/${encodeURIComponent(slug)}`, note ? { body, note } : { body });
5963
+ const response = await adminApiPost(`/api/v1/admin/prompts/${encodeURIComponent(slug)}`, note ? { body, note } : { body });
5949
5964
  return { slug, version: response.version };
5950
5965
  }
5951
5966
  async function promptRollbackCommand(slug, version) {
@@ -5969,7 +5984,7 @@ async function restore(detail, input) {
5969
5984
  if (input.body.trim() === detail.activeBody.trim()) {
5970
5985
  return { from: input.from, skipped: true, slug: detail.slug, version: detail.activeVersion };
5971
5986
  }
5972
- const response = await adminApiPost(`/api/admin/prompts/${encodeURIComponent(detail.slug)}`, { body: input.body, note: input.note });
5987
+ const response = await adminApiPost(`/api/v1/admin/prompts/${encodeURIComponent(detail.slug)}`, { body: input.body, note: input.note });
5973
5988
  return { from: input.from, skipped: false, slug: detail.slug, version: response.version };
5974
5989
  }
5975
5990
  function parseAgainst(value) {
@@ -6084,7 +6099,7 @@ var init_admin_prompts = __esm(() => {
6084
6099
 
6085
6100
  // src/commands/add.ts
6086
6101
  async function addCommand2(spotifyUrl, options) {
6087
- const result = await adminApiPost("/api/admin/tracks", {
6102
+ const result = await adminApiPost("/api/v1/admin/tracks", {
6088
6103
  dryRun: options.dryRun,
6089
6104
  note: options.note,
6090
6105
  spotifyUrl
@@ -6115,7 +6130,7 @@ __export(exports_submissions, {
6115
6130
  });
6116
6131
  import { createInterface as createInterface2 } from "node:readline/promises";
6117
6132
  async function listSubmissionsCommand(options = {}) {
6118
- const response = await adminApiGet("/api/admin/submissions");
6133
+ const response = await adminApiGet("/api/v1/admin/submissions");
6119
6134
  if (options.json) {
6120
6135
  printJson2({ ok: true, submissions: response.submissions });
6121
6136
  return;
@@ -6137,7 +6152,7 @@ async function reviewSubmissionCommand(submissionId, options = {}) {
6137
6152
  console.log(formatSubmissionDetail(submission));
6138
6153
  }
6139
6154
  async function rejectSubmissionCommand(submissionId, options = {}) {
6140
- const response = await adminApiPost(`/api/admin/submissions/${encodeURIComponent(submissionId)}/reject`);
6155
+ const response = await adminApiPost(`/api/v1/admin/submissions/${encodeURIComponent(submissionId)}/reject`);
6141
6156
  if (options.json) {
6142
6157
  printJson2({ ok: true, submission: response.submission });
6143
6158
  return;
@@ -6162,7 +6177,7 @@ async function approveSubmissionCommand(submissionId, options = {}) {
6162
6177
  json: options.json,
6163
6178
  note: submission.note
6164
6179
  });
6165
- const response = await adminApiPost(`/api/admin/submissions/${encodeURIComponent(submission.id)}/approve`);
6180
+ const response = await adminApiPost(`/api/v1/admin/submissions/${encodeURIComponent(submission.id)}/approve`);
6166
6181
  if (options.json) {
6167
6182
  printJson2({ ok: true, submission: response.submission });
6168
6183
  return;
@@ -6170,7 +6185,7 @@ async function approveSubmissionCommand(submissionId, options = {}) {
6170
6185
  console.log(`Approved ${formatTrackLine(submission)}.`);
6171
6186
  }
6172
6187
  async function triageSubmissionCommand(submissionId, verdict, options = {}) {
6173
- const response = await adminApiPost(`/api/admin/submissions/${encodeURIComponent(submissionId)}/triage`, {
6188
+ const response = await adminApiPost(`/api/v1/admin/submissions/${encodeURIComponent(submissionId)}/triage`, {
6174
6189
  ...typeof options.promptVersion === "number" ? { promptVersion: options.promptVersion } : {},
6175
6190
  verdict
6176
6191
  });
@@ -6181,7 +6196,7 @@ async function triageSubmissionCommand(submissionId, verdict, options = {}) {
6181
6196
  console.log(`Triaged ${formatTrackLine(response.submission)}: ${response.submission.triageVerdict ?? ""}`);
6182
6197
  }
6183
6198
  async function fetchSubmission(submissionId) {
6184
- const response = await adminApiGet(`/api/admin/submissions/${encodeURIComponent(submissionId)}`);
6199
+ const response = await adminApiGet(`/api/v1/admin/submissions/${encodeURIComponent(submissionId)}`);
6185
6200
  return response.submission;
6186
6201
  }
6187
6202
  async function confirm(label) {
@@ -6236,7 +6251,7 @@ __export(exports_auth, {
6236
6251
  authSpotifyCommand: () => authSpotifyCommand
6237
6252
  });
6238
6253
  async function authSpotifyCommand() {
6239
- const response = await adminApiGet("/api/admin/spotify/auth/start");
6254
+ const response = await adminApiGet("/api/v1/admin/spotify/auth/start");
6240
6255
  console.log(`Open this Spotify authorization URL:
6241
6256
 
6242
6257
  ${response.authUrl}
@@ -6306,18 +6321,18 @@ async function distributeMixcloud2(mixtapeId, audioPath, onProgress, unlisted =
6306
6321
  const externalId = result.key;
6307
6322
  const url = `https://www.mixcloud.com${result.key}`;
6308
6323
  onProgress?.("Mixcloud: recording the link…");
6309
- await adminApiPost(`/api/admin/mixtapes/${encodeURIComponent(mixtapeId)}/mixcloud/finalize`, {
6324
+ await adminApiPost(`/api/v1/admin/mixtapes/${encodeURIComponent(mixtapeId)}/mixcloud/finalize`, {
6310
6325
  externalId,
6311
6326
  url
6312
6327
  });
6313
6328
  return { url };
6314
6329
  }
6315
6330
  async function resyncMixcloud2(mixtapeId) {
6316
- const response = await adminApiPost(`/api/admin/mixtapes/${encodeURIComponent(mixtapeId)}/mixcloud/resync`);
6331
+ const response = await adminApiPost(`/api/v1/admin/mixtapes/${encodeURIComponent(mixtapeId)}/mixcloud/resync`);
6317
6332
  return { url: response.url };
6318
6333
  }
6319
6334
  async function authMixcloudCommand2() {
6320
- const response = await adminApiGet("/api/admin/mixcloud/auth/start");
6335
+ const response = await adminApiGet("/api/v1/admin/mixcloud/auth/start");
6321
6336
  console.log(`Open this Mixcloud authorization URL:
6322
6337
 
6323
6338
  ${response.authUrl}
@@ -6344,7 +6359,7 @@ function mixtapeTags2(_mixtape) {
6344
6359
  }
6345
6360
  async function fetchMixcloudToken2() {
6346
6361
  try {
6347
- const response = await adminApiPost("/api/admin/mixcloud/token");
6362
+ const response = await adminApiPost("/api/v1/admin/mixcloud/token");
6348
6363
  return response.accessToken;
6349
6364
  } catch {
6350
6365
  throw new CliError2("mixcloud_not_connected", "Mixcloud is not connected. Run `fluncle admin auth mixcloud` to authorize it.");
@@ -6396,7 +6411,7 @@ __export(exports_auth_tiktok, {
6396
6411
  authTikTokCommand: () => authTikTokCommand
6397
6412
  });
6398
6413
  async function authTikTokCommand() {
6399
- const response = await adminApiGet("/api/admin/tiktok/auth/start");
6414
+ const response = await adminApiGet("/api/v1/admin/tiktok/auth/start");
6400
6415
  console.log(`Open this TikTok authorization URL:
6401
6416
 
6402
6417
  ${response.authUrl}
@@ -6414,7 +6429,7 @@ __export(exports_auth_lastfm, {
6414
6429
  });
6415
6430
  async function authLastfmCommand(options) {
6416
6431
  if (options.token?.trim()) {
6417
- const response2 = await adminApiPost("/api/admin/lastfm/auth/session", { token: options.token.trim() });
6432
+ const response2 = await adminApiPost("/api/v1/admin/lastfm/auth/session", { token: options.token.trim() });
6418
6433
  console.log(`Last.fm connected as ${response2.name || "fluncle"}.
6419
6434
 
6420
6435
  Set this as the Worker secret LASTFM_SESSION_KEY (it does not expire):
@@ -6426,7 +6441,7 @@ ${response2.sessionKey}
6426
6441
  Also store it in 1Password (Fluncle vault) alongside the API key + shared secret.`);
6427
6442
  return;
6428
6443
  }
6429
- const response = await adminApiGet("/api/admin/lastfm/auth/start");
6444
+ const response = await adminApiGet("/api/v1/admin/lastfm/auth/start");
6430
6445
  console.log(`Open this Last.fm authorization URL (logged in as fluncle) and click "Yes, allow access":
6431
6446
 
6432
6447
  ${response.authUrl}
@@ -6447,7 +6462,7 @@ __export(exports_admin_notes, {
6447
6462
  });
6448
6463
  async function noteHeldCommand(options) {
6449
6464
  const query = options.settled ? "?open=false" : "";
6450
- return adminApiGet(`/api/admin/note-rejections${query}`);
6465
+ return adminApiGet(`/api/v1/admin/note-rejections${query}`);
6451
6466
  }
6452
6467
  async function noteGateCommand(options) {
6453
6468
  const patch = {};
@@ -6458,10 +6473,10 @@ async function noteGateCommand(options) {
6458
6473
  patch.maxOverlap = options.maxOverlap;
6459
6474
  }
6460
6475
  if (Object.keys(patch).length === 0) {
6461
- const response2 = await adminApiGet("/api/admin/note-rejections");
6476
+ const response2 = await adminApiGet("/api/v1/admin/note-rejections");
6462
6477
  return response2.gate;
6463
6478
  }
6464
- const response = await adminApiPatch("/api/admin/note-gate", patch);
6479
+ const response = await adminApiPatch("/api/v1/admin/note-gate", patch);
6465
6480
  return response.gate;
6466
6481
  }
6467
6482
  var init_admin_notes = __esm(() => {
@@ -6476,7 +6491,7 @@ __export(exports_admin_observations, {
6476
6491
  });
6477
6492
  async function observationHeldCommand(options) {
6478
6493
  const query = options.settled ? "?open=false" : "";
6479
- return adminApiGet(`/api/admin/observation-rejections${query}`);
6494
+ return adminApiGet(`/api/v1/admin/observation-rejections${query}`);
6480
6495
  }
6481
6496
  async function observationGateCommand(options) {
6482
6497
  const patch = {};
@@ -6487,10 +6502,10 @@ async function observationGateCommand(options) {
6487
6502
  patch.maxOverlap = options.maxOverlap;
6488
6503
  }
6489
6504
  if (Object.keys(patch).length === 0) {
6490
- const response2 = await adminApiGet("/api/admin/observation-rejections");
6505
+ const response2 = await adminApiGet("/api/v1/admin/observation-rejections");
6491
6506
  return response2.gate;
6492
6507
  }
6493
- const response = await adminApiPatch("/api/admin/observation-gate", patch);
6508
+ const response = await adminApiPatch("/api/v1/admin/observation-gate", patch);
6494
6509
  return response.gate;
6495
6510
  }
6496
6511
  var init_admin_observations = __esm(() => {
@@ -6506,13 +6521,13 @@ __export(exports_admin_frontier, {
6506
6521
  });
6507
6522
  async function frontierRefreshCommand(options) {
6508
6523
  const limit = options.limit ? Number.parseInt(options.limit, 10) : undefined;
6509
- return adminApiPost("/api/admin/frontier-playlists/refresh", limit ? { limit } : {});
6524
+ return adminApiPost("/api/v1/admin/frontier-playlists/refresh", limit ? { limit } : {});
6510
6525
  }
6511
6526
  async function frontierStatusCommand() {
6512
- return adminApiGet("/api/admin/frontier/minting");
6527
+ return adminApiGet("/api/v1/admin/frontier/minting");
6513
6528
  }
6514
6529
  async function frontierSetMintingCommand(open) {
6515
- return adminApiPut("/api/admin/frontier/minting", { open });
6530
+ return adminApiPut("/api/v1/admin/frontier/minting", { open });
6516
6531
  }
6517
6532
  var init_admin_frontier = __esm(() => {
6518
6533
  init_api();
@@ -6537,11 +6552,11 @@ __export(exports_admin_catalogue, {
6537
6552
  });
6538
6553
  async function catalogueRankCommand(options) {
6539
6554
  const limit = options.limit ? Number.parseInt(options.limit, 10) : undefined;
6540
- const response = await adminApiPost("/api/admin/catalogue/rank", limit ? { limit } : {});
6555
+ const response = await adminApiPost("/api/v1/admin/catalogue/rank", limit ? { limit } : {});
6541
6556
  return { summary: response.summary, telescope: response.telescope };
6542
6557
  }
6543
6558
  async function catalogueDemandCommand() {
6544
- const response = await adminApiPost("/api/admin/catalogue/demand", {});
6559
+ const response = await adminApiPost("/api/v1/admin/catalogue/demand", {});
6545
6560
  return response.summary;
6546
6561
  }
6547
6562
  async function catalogueListCommand(options) {
@@ -6550,34 +6565,34 @@ async function catalogueListCommand(options) {
6550
6565
  if (options.limit) {
6551
6566
  params.set("limit", options.limit);
6552
6567
  }
6553
- return adminApiGet(`/api/admin/catalogue?${params.toString()}`);
6568
+ return adminApiGet(`/api/v1/admin/catalogue?${params.toString()}`);
6554
6569
  }
6555
6570
  async function clearWrongAudioCommand(trackId) {
6556
- return adminApiPost("/api/admin/catalogue/wrong-audio/clear", {
6571
+ return adminApiPost("/api/v1/admin/catalogue/wrong-audio/clear", {
6557
6572
  trackId
6558
6573
  });
6559
6574
  }
6560
6575
  async function requeueUnmatchedCommand() {
6561
- return adminApiPost("/api/admin/catalogue/captures/requeue-unmatched", {});
6576
+ return adminApiPost("/api/v1/admin/catalogue/captures/requeue-unmatched", {});
6562
6577
  }
6563
6578
  async function forceCaptureCommand(trackId) {
6564
- return adminApiPost("/api/admin/catalogue/force-capture", {
6579
+ return adminApiPost("/api/v1/admin/catalogue/force-capture", {
6565
6580
  trackId
6566
6581
  });
6567
6582
  }
6568
6583
  async function flagWrongAudioCommand(trackId) {
6569
- return adminApiPost("/api/admin/catalogue/wrong-audio/flag", {
6584
+ return adminApiPost("/api/v1/admin/catalogue/wrong-audio/flag", {
6570
6585
  trackId
6571
6586
  });
6572
6587
  }
6573
6588
  async function certifyTrackCommand(trackId, note) {
6574
- return adminApiPost("/api/admin/catalogue/certify", {
6589
+ return adminApiPost("/api/v1/admin/catalogue/certify", {
6575
6590
  ...note ? { note } : {},
6576
6591
  trackId
6577
6592
  });
6578
6593
  }
6579
6594
  async function setTrackDismissedCommand(trackId, dismissed) {
6580
- return adminApiPut("/api/admin/catalogue/dismissed", {
6595
+ return adminApiPut("/api/v1/admin/catalogue/dismissed", {
6581
6596
  dismissed,
6582
6597
  trackId
6583
6598
  });
@@ -6587,10 +6602,10 @@ async function listUnverifiedCapturesCommand(options) {
6587
6602
  if (options.limit) {
6588
6603
  params.set("limit", options.limit);
6589
6604
  }
6590
- return adminApiGet(`/api/admin/catalogue/captures/unverified?${params.toString()}`);
6605
+ return adminApiGet(`/api/v1/admin/catalogue/captures/unverified?${params.toString()}`);
6591
6606
  }
6592
6607
  async function verifyCaptureCommand(trackId, verdict) {
6593
- return adminApiPost("/api/admin/catalogue/captures/verify", {
6608
+ return adminApiPost("/api/v1/admin/catalogue/captures/verify", {
6594
6609
  trackId,
6595
6610
  verdict
6596
6611
  });
@@ -6600,10 +6615,10 @@ async function crawlCatalogueCommand(limit, maxHop, dryRun) {
6600
6615
  if (dryRun) {
6601
6616
  params.set("dryRun", "true");
6602
6617
  }
6603
- return adminApiPost(`/api/admin/catalogue/crawl?${params.toString()}`);
6618
+ return adminApiPost(`/api/v1/admin/catalogue/crawl?${params.toString()}`);
6604
6619
  }
6605
6620
  async function crawlStatusCommand() {
6606
- return adminApiGet("/api/admin/catalogue/crawl");
6621
+ return adminApiGet("/api/v1/admin/catalogue/crawl");
6607
6622
  }
6608
6623
  var CATALOGUE_LENSES;
6609
6624
  var init_admin_catalogue = __esm(() => {
@@ -6617,7 +6632,7 @@ __export(exports_admin_reach, {
6617
6632
  reachCollectCommand: () => reachCollectCommand
6618
6633
  });
6619
6634
  async function reachCollectCommand() {
6620
- return adminApiPost("/api/admin/reach/collect", {});
6635
+ return adminApiPost("/api/v1/admin/reach/collect", {});
6621
6636
  }
6622
6637
  var init_admin_reach = __esm(() => {
6623
6638
  init_api();
@@ -6647,13 +6662,13 @@ function buildBioBody(options) {
6647
6662
  return body;
6648
6663
  }
6649
6664
  async function describeArtistCommand(slug, options) {
6650
- return adminApiPost(`/api/admin/artists/${encodeURIComponent(slug)}/bio`, buildBioBody(options));
6665
+ return adminApiPost(`/api/v1/admin/artists/${encodeURIComponent(slug)}/bio`, buildBioBody(options));
6651
6666
  }
6652
6667
  async function draftArtistBioCommand(slug) {
6653
- return adminApiGet(`/api/admin/artists/${encodeURIComponent(slug)}/bio-draft`);
6668
+ return adminApiGet(`/api/v1/admin/artists/${encodeURIComponent(slug)}/bio-draft`);
6654
6669
  }
6655
6670
  async function artistsBioQueueCommand(limit) {
6656
- const response = await adminApiGet(`/api/admin/artists/bio-queue?limit=${limit}`);
6671
+ const response = await adminApiGet(`/api/v1/admin/artists/bio-queue?limit=${limit}`);
6657
6672
  return response.artists;
6658
6673
  }
6659
6674
  async function listArtistsCommand(limit, cursor) {
@@ -6661,14 +6676,14 @@ async function listArtistsCommand(limit, cursor) {
6661
6676
  if (cursor) {
6662
6677
  params.set("cursor", cursor);
6663
6678
  }
6664
- return adminApiGet(`/api/admin/artists?${params.toString()}`);
6679
+ return adminApiGet(`/api/v1/admin/artists?${params.toString()}`);
6665
6680
  }
6666
6681
  async function resolveArtistCommand(artistId) {
6667
- return adminApiPost(`/api/admin/artists/${encodeURIComponent(artistId)}/resolve`);
6682
+ return adminApiPost(`/api/v1/admin/artists/${encodeURIComponent(artistId)}/resolve`);
6668
6683
  }
6669
6684
  async function rankArtistsCommand(options) {
6670
6685
  const limit = options.limit ? Number.parseInt(options.limit, 10) : undefined;
6671
- const response = await adminApiPost("/api/admin/artists/rank", limit ? { limit } : {});
6686
+ const response = await adminApiPost("/api/v1/admin/artists/rank", limit ? { limit } : {});
6672
6687
  return { summary: response.summary };
6673
6688
  }
6674
6689
  async function backfillArtistImagesCommand(limit, dryRun, cursor) {
@@ -6676,14 +6691,14 @@ async function backfillArtistImagesCommand(limit, dryRun, cursor) {
6676
6691
  if (cursor) {
6677
6692
  params.set("cursor", cursor);
6678
6693
  }
6679
- return adminApiPost(`/api/admin/backfill/artist-images?${params.toString()}`);
6694
+ return adminApiPost(`/api/v1/admin/backfill/artist-images?${params.toString()}`);
6680
6695
  }
6681
6696
  async function backfillArtistsCommand(limit, dryRun, cursor) {
6682
6697
  const params = new URLSearchParams({ dryRun: String(dryRun), limit: String(limit) });
6683
6698
  if (cursor) {
6684
6699
  params.set("cursor", cursor);
6685
6700
  }
6686
- return adminApiPost(`/api/admin/backfill/artists?${params.toString()}`);
6701
+ return adminApiPost(`/api/v1/admin/backfill/artists?${params.toString()}`);
6687
6702
  }
6688
6703
  var init_admin_artists = __esm(() => {
6689
6704
  init_api();
@@ -6715,17 +6730,17 @@ __export(exports_admin_labels, {
6715
6730
  backfillLabelImagesCommand: () => backfillLabelImagesCommand
6716
6731
  });
6717
6732
  async function mergeLabelCommand(losingSlug, canonicalSlug) {
6718
- const response = await adminApiPost(`/api/admin/labels/${encodeURIComponent(losingSlug)}/merge`, { canonicalSlug });
6733
+ const response = await adminApiPost(`/api/v1/admin/labels/${encodeURIComponent(losingSlug)}/merge`, { canonicalSlug });
6719
6734
  return response.result;
6720
6735
  }
6721
6736
  async function describeLabelCommand(slug, options) {
6722
- return adminApiPost(`/api/admin/labels/${encodeURIComponent(slug)}/bio`, buildBioBody2(options));
6737
+ return adminApiPost(`/api/v1/admin/labels/${encodeURIComponent(slug)}/bio`, buildBioBody2(options));
6723
6738
  }
6724
6739
  async function draftLabelBioCommand(slug) {
6725
- return adminApiGet(`/api/admin/labels/${encodeURIComponent(slug)}/bio-draft`);
6740
+ return adminApiGet(`/api/v1/admin/labels/${encodeURIComponent(slug)}/bio-draft`);
6726
6741
  }
6727
6742
  async function labelsBioQueueCommand(limit) {
6728
- const response = await adminApiGet(`/api/admin/labels/bio-queue?limit=${limit}`);
6743
+ const response = await adminApiGet(`/api/v1/admin/labels/bio-queue?limit=${limit}`);
6729
6744
  return response.labels;
6730
6745
  }
6731
6746
  async function backfillLabelImagesCommand(limit, dryRun, cursor) {
@@ -6733,14 +6748,14 @@ async function backfillLabelImagesCommand(limit, dryRun, cursor) {
6733
6748
  if (cursor) {
6734
6749
  params.set("cursor", cursor);
6735
6750
  }
6736
- return adminApiPost(`/api/admin/backfill/label-images?${params.toString()}`);
6751
+ return adminApiPost(`/api/v1/admin/backfill/label-images?${params.toString()}`);
6737
6752
  }
6738
6753
  async function backfillLabelLineageCommand(limit, dryRun, cursor) {
6739
6754
  const params = new URLSearchParams({ dryRun: String(dryRun), limit: String(limit) });
6740
6755
  if (cursor) {
6741
6756
  params.set("cursor", cursor);
6742
6757
  }
6743
- return adminApiPost(`/api/admin/backfill/label-lineage?${params.toString()}`);
6758
+ return adminApiPost(`/api/v1/admin/backfill/label-lineage?${params.toString()}`);
6744
6759
  }
6745
6760
  var init_admin_labels = __esm(() => {
6746
6761
  init_api();
@@ -6760,7 +6775,7 @@ async function backfillCoverMastersCommand(kind, limit, dryRun, cursor, retryNon
6760
6775
  if (retryNone) {
6761
6776
  params.set("retry", "none");
6762
6777
  }
6763
- return adminApiPost(`/api/admin/backfill/cover-masters?${params.toString()}`);
6778
+ return adminApiPost(`/api/v1/admin/backfill/cover-masters?${params.toString()}`);
6764
6779
  }
6765
6780
  var init_admin_covers = __esm(() => {
6766
6781
  init_api();
@@ -6774,13 +6789,13 @@ __export(exports_admin_albums, {
6774
6789
  albumsBioQueueCommand: () => albumsBioQueueCommand
6775
6790
  });
6776
6791
  async function describeAlbumCommand(slug, options) {
6777
- return adminApiPost(`/api/admin/albums/${encodeURIComponent(slug)}/bio`, buildBioBody2(options));
6792
+ return adminApiPost(`/api/v1/admin/albums/${encodeURIComponent(slug)}/bio`, buildBioBody2(options));
6778
6793
  }
6779
6794
  async function draftAlbumBioCommand(slug) {
6780
- return adminApiGet(`/api/admin/albums/${encodeURIComponent(slug)}/bio-draft`);
6795
+ return adminApiGet(`/api/v1/admin/albums/${encodeURIComponent(slug)}/bio-draft`);
6781
6796
  }
6782
6797
  async function albumsBioQueueCommand(limit) {
6783
- const response = await adminApiGet(`/api/admin/albums/bio-queue?limit=${limit}`);
6798
+ const response = await adminApiGet(`/api/v1/admin/albums/bio-queue?limit=${limit}`);
6784
6799
  return response.albums;
6785
6800
  }
6786
6801
  var init_admin_albums = __esm(() => {
@@ -6802,7 +6817,7 @@ async function migratePreviewArchiveCommand(args) {
6802
6817
  if (args.cursor) {
6803
6818
  params.set("cursor", args.cursor);
6804
6819
  }
6805
- return adminApiPost(`/api/admin/migrations/preview-archive?${params.toString()}`);
6820
+ return adminApiPost(`/api/v1/admin/migrations/preview-archive?${params.toString()}`);
6806
6821
  }
6807
6822
  var init_preview_migration = __esm(() => {
6808
6823
  init_api();
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.186.0"
34
+ "version": "0.187.0"
35
35
  }