fluncle 0.55.0 → 0.57.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 +133 -7
  2. package/package.json +1 -1
package/bin/fluncle.mjs CHANGED
@@ -423,7 +423,7 @@ function parseVersion(version) {
423
423
  var currentVersion;
424
424
  var init_version = __esm(() => {
425
425
  init_output();
426
- currentVersion = "0.55.0".trim() ? "0.55.0".trim() : "0.1.0";
426
+ currentVersion = "0.57.0".trim() ? "0.57.0".trim() : "0.1.0";
427
427
  });
428
428
 
429
429
  // src/update-notifier.ts
@@ -1912,7 +1912,7 @@ function parseVersion2(version) {
1912
1912
  var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
1913
1913
  var init_version2 = __esm(() => {
1914
1914
  init_output();
1915
- currentVersion2 = "0.55.0".trim() ? "0.55.0".trim() : "0.1.0";
1915
+ currentVersion2 = "0.57.0".trim() ? "0.57.0".trim() : "0.1.0";
1916
1916
  });
1917
1917
 
1918
1918
  // src/commands/track.ts
@@ -1923,6 +1923,7 @@ __export(exports_track, {
1923
1923
  trackSocialUpdateCommand: () => trackSocialUpdateCommand,
1924
1924
  trackSocialShowCommand: () => trackSocialShowCommand,
1925
1925
  trackObserveCommand: () => trackObserveCommand,
1926
+ trackNoteCommand: () => trackNoteCommand,
1926
1927
  trackGetCommand: () => trackGetCommand,
1927
1928
  trackDraftCommand: () => trackDraftCommand,
1928
1929
  trackContextCommand: () => trackContextCommand
@@ -2043,8 +2044,15 @@ async function trackContextCommand(idOrLogId, options = {}) {
2043
2044
  if (options.query !== undefined) {
2044
2045
  body.query = options.query;
2045
2046
  }
2047
+ if (options.refresh) {
2048
+ body.refresh = true;
2049
+ }
2046
2050
  return adminApiPost(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/context`, body);
2047
2051
  }
2052
+ async function trackNoteCommand(idOrLogId, options) {
2053
+ const body = { note: options.note };
2054
+ return adminApiPost(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/note`, body);
2055
+ }
2048
2056
  var DEFAULT_VIDEO_MODEL = "anthropic/claude-opus-4-8", DEFAULT_VIDEO_REASONING = "high", FOUND_BASE = "https://found.fluncle.com", VIDEO_FIELDS;
2049
2057
  var init_track = __esm(() => {
2050
2058
  init_api();
@@ -2094,13 +2102,15 @@ __export(exports_admin_tracks, {
2094
2102
  vehiclesCommand: () => vehiclesCommand,
2095
2103
  queueCommand: () => queueCommand,
2096
2104
  observeQueueCommand: () => observeQueueCommand,
2105
+ noteQueueCommand: () => noteQueueCommand,
2097
2106
  enrichQueueCommand: () => enrichQueueCommand,
2098
2107
  contextQueueCommand: () => contextQueueCommand,
2099
2108
  backfillLastfmCommand: () => backfillLastfmCommand,
2100
- backfillDiscogsCommand: () => backfillDiscogsCommand
2109
+ backfillDiscogsCommand: () => backfillDiscogsCommand,
2110
+ backfillAlignmentCommand: () => backfillAlignmentCommand
2101
2111
  });
2102
2112
  async function fetchAdminTracks(options) {
2103
- const { hasContext, hasObservation, hasVideo, max, order, status } = options;
2113
+ const { hasContext, hasNote, hasObservation, hasVideo, max, order, status } = options;
2104
2114
  const results = [];
2105
2115
  let cursor;
2106
2116
  do {
@@ -2111,6 +2121,9 @@ async function fetchAdminTracks(options) {
2111
2121
  if (hasContext !== undefined) {
2112
2122
  params.set("hasContext", String(hasContext));
2113
2123
  }
2124
+ if (hasNote !== undefined) {
2125
+ params.set("hasNote", String(hasNote));
2126
+ }
2114
2127
  if (hasObservation !== undefined) {
2115
2128
  params.set("hasObservation", String(hasObservation));
2116
2129
  }
@@ -2158,6 +2171,14 @@ async function observeQueueCommand(limit) {
2158
2171
  order: "asc"
2159
2172
  });
2160
2173
  }
2174
+ async function noteQueueCommand(limit) {
2175
+ return fetchAdminTracks({
2176
+ hasContext: true,
2177
+ hasNote: false,
2178
+ max: limit,
2179
+ order: "asc"
2180
+ });
2181
+ }
2161
2182
  async function backfillLastfmCommand(limit, dryRun, cursor) {
2162
2183
  const params = new URLSearchParams({ dryRun: String(dryRun), limit: String(limit) });
2163
2184
  if (cursor) {
@@ -2172,6 +2193,13 @@ async function backfillDiscogsCommand(limit, dryRun, cursor) {
2172
2193
  }
2173
2194
  return adminApiPost(`/api/admin/backfill/discogs?${params.toString()}`);
2174
2195
  }
2196
+ async function backfillAlignmentCommand(limit, dryRun, cursor) {
2197
+ const params = new URLSearchParams({ dryRun: String(dryRun), limit: String(limit) });
2198
+ if (cursor) {
2199
+ params.set("cursor", cursor);
2200
+ }
2201
+ return adminApiPost(`/api/admin/backfill/alignment?${params.toString()}`);
2202
+ }
2175
2203
  async function vehiclesCommand(limit) {
2176
2204
  const tracks = await fetchAdminTracks({ hasVideo: true, max: limit, order: "desc" });
2177
2205
  return tracks.map((track) => ({
@@ -5483,7 +5511,7 @@ function addAdminCommands(program2) {
5483
5511
  const { trackObserveCommand: trackObserveCommand2 } = await Promise.resolve().then(() => (init_track(), exports_track));
5484
5512
  await runTrackObserve(idOrLogId, options, trackObserveCommand2);
5485
5513
  });
5486
- adminTrack.command("context").description("Gather the field notes for a finding (facts only; observe speaks from them)").argument("[idOrLogId]").option("--queue", "Show the context worklist (findings missing field notes), oldest first", false).option("--limit <limit>", "Number of findings to show with --queue", "10").option("--query <text>", "Override the fact-search query (else the Worker builds one)").option("--json", "Print JSON", false).allowExcessArguments().action(async (idOrLogId, options) => {
5514
+ adminTrack.command("context").description("Gather the field notes for a finding (facts only; observe speaks from them)").argument("[idOrLogId]").option("--queue", "Show the context worklist (findings missing field notes), oldest first", false).option("--limit <limit>", "Number of findings to show with --queue", "10").option("--query <text>", "Override the fact-search query (else the Worker builds one)").option("--refresh", "Re-run the fetch even if a note exists (backfill/sharpen)", false).option("--json", "Print JSON", false).allowExcessArguments().action(async (idOrLogId, options) => {
5487
5515
  if (options.queue) {
5488
5516
  const { contextQueueCommand: contextQueueCommand2 } = await Promise.resolve().then(() => (init_admin_tracks(), exports_admin_tracks));
5489
5517
  await runAdminContextQueue(options, contextQueueCommand2);
@@ -5492,6 +5520,15 @@ function addAdminCommands(program2) {
5492
5520
  const { trackContextCommand: trackContextCommand2 } = await Promise.resolve().then(() => (init_track(), exports_track));
5493
5521
  await runTrackContext(idOrLogId, options, trackContextCommand2);
5494
5522
  });
5523
+ adminTrack.command("note").description("Author the editorial note for a finding (fills an empty note only)").argument("[idOrLogId]").option("--queue", "Show the note worklist (context'd findings with no note yet), oldest first", false).option("--limit <limit>", "Number of findings to show with --queue", "10").option("--script <text>", "The voice-gated editorial note").option("--script-file <file>", "Read the editorial note from a file").option("--json", "Print JSON", false).allowExcessArguments().action(async (idOrLogId, options) => {
5524
+ if (options.queue) {
5525
+ const { noteQueueCommand: noteQueueCommand2 } = await Promise.resolve().then(() => (init_admin_tracks(), exports_admin_tracks));
5526
+ await runAdminNoteQueue(options, noteQueueCommand2);
5527
+ return;
5528
+ }
5529
+ const { trackNoteCommand: trackNoteCommand2 } = await Promise.resolve().then(() => (init_track(), exports_track));
5530
+ await runTrackNote(idOrLogId, options, trackNoteCommand2);
5531
+ });
5495
5532
  const adminMixtapes = configureCommand(admin.command("mixtapes").description("Mixtape admin commands"));
5496
5533
  adminMixtapes.action(() => {
5497
5534
  adminMixtapes.outputHelp();
@@ -5611,6 +5648,10 @@ function addAdminCommands(program2) {
5611
5648
  const { backfillDiscogsCommand: backfillDiscogsCommand2 } = await Promise.resolve().then(() => (init_admin_tracks(), exports_admin_tracks));
5612
5649
  await runBackfillDiscogs(options, backfillDiscogsCommand2);
5613
5650
  });
5651
+ backfill.command("alignment").description("Back-fill word-level caption timings for observations rendered before timestamps (no re-render)").option("--dry-run", "Report the eligible set but align nothing", false).option("--limit <limit>", "Max observations to align", "50").option("--json", "Print JSON", false).action(async (options) => {
5652
+ const { backfillAlignmentCommand: backfillAlignmentCommand2 } = await Promise.resolve().then(() => (init_admin_tracks(), exports_admin_tracks));
5653
+ await runBackfillAlignment(options, backfillAlignmentCommand2);
5654
+ });
5614
5655
  }
5615
5656
  async function runTrackPreviewArchive(idOrLogId, options, previewArchiveUploadCommand2) {
5616
5657
  if (!idOrLogId || !options.file || !options.source || !options.mime) {
@@ -5662,9 +5703,12 @@ async function runTrackObserve(idOrLogId, options, trackObserveCommand2) {
5662
5703
  }
5663
5704
  async function runTrackContext(idOrLogId, options, trackContextCommand2) {
5664
5705
  if (!idOrLogId) {
5665
- throw new Error("Usage: fluncle admin tracks context <track_id|log_id> [--query <text>] [--json]");
5706
+ throw new Error("Usage: fluncle admin tracks context <track_id|log_id> [--query <text>] [--refresh] [--json]");
5666
5707
  }
5667
- const result = await trackContextCommand2(idOrLogId, { query: options.query });
5708
+ const result = await trackContextCommand2(idOrLogId, {
5709
+ query: options.query,
5710
+ refresh: options.refresh
5711
+ });
5668
5712
  if (options.json) {
5669
5713
  printJson(result);
5670
5714
  return;
@@ -5683,6 +5727,23 @@ async function runTrackContext(idOrLogId, options, trackContextCommand2) {
5683
5727
  console.log(` sources: ${result.sources.join(", ")}`);
5684
5728
  }
5685
5729
  }
5730
+ async function runTrackNote(idOrLogId, options, trackNoteCommand2) {
5731
+ const note = options.scriptFile ? readFileSync3(options.scriptFile, "utf8") : options.script;
5732
+ if (!idOrLogId || !note || !note.trim()) {
5733
+ throw new Error("Usage: fluncle admin tracks note <track_id|log_id> (--script <text> | --script-file <file>) [--json]");
5734
+ }
5735
+ const result = await trackNoteCommand2(idOrLogId, { note: note.trim() });
5736
+ if (options.json) {
5737
+ printJson(result);
5738
+ return;
5739
+ }
5740
+ if (result.skipped) {
5741
+ console.log(`A note is already on file for ${result.logId}. The operator's note stands.`);
5742
+ return;
5743
+ }
5744
+ console.log(`Authored the note for ${result.logId}:`);
5745
+ console.log(` ${result.note}`);
5746
+ }
5686
5747
  async function runPreviewArchiveBackfill(options, previewArchiveBackfillCommand2) {
5687
5748
  const limit = options.limit === undefined ? undefined : Number.parseInt(options.limit, 10);
5688
5749
  if (limit !== undefined && (!Number.isInteger(limit) || limit < 1)) {
@@ -5791,6 +5852,51 @@ async function runBackfillDiscogs(options, backfillDiscogsCommand2) {
5791
5852
  console.log(` ${item.logId}: release ${item.releaseId}${master}`);
5792
5853
  }
5793
5854
  }
5855
+ async function runBackfillAlignment(options, backfillAlignmentCommand2) {
5856
+ const limit = parseListLimit(options.limit);
5857
+ const aligned = [];
5858
+ const empty = [];
5859
+ const failed = [];
5860
+ let cursor;
5861
+ let dryRun = options.dryRun;
5862
+ while (aligned.length + empty.length + failed.length < limit) {
5863
+ const remaining = limit - (aligned.length + empty.length + failed.length);
5864
+ const result = await backfillAlignmentCommand2(remaining, options.dryRun, cursor);
5865
+ dryRun = result.dryRun;
5866
+ aligned.push(...result.aligned);
5867
+ empty.push(...result.empty);
5868
+ failed.push(...result.failed);
5869
+ if (!options.json) {
5870
+ const verb2 = result.dryRun ? "would align" : "aligned";
5871
+ console.log(` \u2026${verb2} ${result.alignedCount}; ${result.emptyCount} empty; ${result.failedCount} failed`);
5872
+ }
5873
+ if (result.nextCursor === null) {
5874
+ break;
5875
+ }
5876
+ cursor = result.nextCursor;
5877
+ }
5878
+ if (options.json) {
5879
+ printJson({
5880
+ aligned,
5881
+ alignedCount: aligned.length,
5882
+ dryRun,
5883
+ empty,
5884
+ emptyCount: empty.length,
5885
+ failed,
5886
+ failedCount: failed.length,
5887
+ ok: true
5888
+ });
5889
+ return;
5890
+ }
5891
+ const verb = dryRun ? "Would align" : "Aligned";
5892
+ console.log(`${verb} ${aligned.length} observation(s); ${empty.length} empty; ${failed.length} failed.`);
5893
+ for (const logId of aligned) {
5894
+ console.log(` ${logId}`);
5895
+ }
5896
+ for (const item of failed) {
5897
+ console.log(` ${item.logId}: ${item.error}`);
5898
+ }
5899
+ }
5794
5900
  async function runTrackVideo(idOrLogId, options, trackVideoCommand2) {
5795
5901
  if (!idOrLogId) {
5796
5902
  throw new Error("Missing id. Usage: fluncle admin tracks video <track_id|log_id> (--dir <dir> | --footage <file> [--footage-social <file>] [--footage-silent <file>] [--poster <file>] [--cover <file>] [--note <file>] [--composition <file>] [--props <file>] [--render <file>])");
@@ -6250,6 +6356,26 @@ async function runAdminObserveQueue(options, observeQueueCommand2) {
6250
6356
  console.log(trackRows2(tracks).join(`
6251
6357
  `));
6252
6358
  }
6359
+ async function runAdminNoteQueue(options, noteQueueCommand2) {
6360
+ const limit = parseListLimit(options.limit);
6361
+ const tracks = await noteQueueCommand2(limit);
6362
+ if (options.json) {
6363
+ printJson({
6364
+ ok: true,
6365
+ tracks
6366
+ });
6367
+ return;
6368
+ }
6369
+ if (tracks.length === 0) {
6370
+ console.log("Every context'd finding has a note. Nothing waiting on the uncle's words.");
6371
+ return;
6372
+ }
6373
+ const { trackRows: trackRows2 } = await Promise.resolve().then(() => (init_format2(), exports_format));
6374
+ const noun = tracks.length === 1 ? "finding" : "findings";
6375
+ console.log(`${tracks.length} ${noun} awaiting a note, oldest first:`);
6376
+ console.log(trackRows2(tracks).join(`
6377
+ `));
6378
+ }
6253
6379
  async function runAdminEnrichQueue(options, enrichQueueCommand2) {
6254
6380
  const limit = parseListLimit(options.limit);
6255
6381
  const tracks = await enrichQueueCommand2(limit);
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.55.0"
34
+ "version": "0.57.0"
35
35
  }