fluncle 0.89.0 → 0.90.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/fluncle.mjs +37 -7
- package/package.json +1 -1
package/bin/fluncle.mjs
CHANGED
|
@@ -538,7 +538,7 @@ function parseVersion(version) {
|
|
|
538
538
|
var currentVersion;
|
|
539
539
|
var init_version = __esm(() => {
|
|
540
540
|
init_output();
|
|
541
|
-
currentVersion = "0.
|
|
541
|
+
currentVersion = "0.90.0".trim() ? "0.90.0".trim() : "0.1.0";
|
|
542
542
|
});
|
|
543
543
|
|
|
544
544
|
// src/update-notifier.ts
|
|
@@ -2168,7 +2168,7 @@ function parseVersion2(version) {
|
|
|
2168
2168
|
var currentVersion2, latestReleaseUrl = "https://api.github.com/repos/mauricekleine/fluncle/releases/latest";
|
|
2169
2169
|
var init_version2 = __esm(() => {
|
|
2170
2170
|
init_output();
|
|
2171
|
-
currentVersion2 = "0.
|
|
2171
|
+
currentVersion2 = "0.90.0".trim() ? "0.90.0".trim() : "0.1.0";
|
|
2172
2172
|
});
|
|
2173
2173
|
|
|
2174
2174
|
// ../../packages/registry/src/index.ts
|
|
@@ -2895,17 +2895,30 @@ __export(exports_track, {
|
|
|
2895
2895
|
trackGetCommand: () => trackGetCommand,
|
|
2896
2896
|
trackDraftCommand: () => trackDraftCommand,
|
|
2897
2897
|
trackContextCommand: () => trackContextCommand,
|
|
2898
|
+
isPlatesOnlyUpload: () => isPlatesOnlyUpload,
|
|
2898
2899
|
checkBundleCompleteness: () => checkBundleCompleteness
|
|
2899
2900
|
});
|
|
2900
2901
|
async function trackGetCommand(idOrLogId) {
|
|
2901
2902
|
return publicApiGet(`/api/tracks/${encodeURIComponent(idOrLogId)}`);
|
|
2902
2903
|
}
|
|
2904
|
+
function isPlatesOnlyUpload(files) {
|
|
2905
|
+
const hasPlate = PLATE_FIELDS.some((option) => Boolean(files[option]));
|
|
2906
|
+
if (!hasPlate) {
|
|
2907
|
+
return false;
|
|
2908
|
+
}
|
|
2909
|
+
return Object.keys(files).every((option) => !files[option] || PLATE_FIELDS.includes(option) || NON_FILE_OPTIONS.includes(option));
|
|
2910
|
+
}
|
|
2903
2911
|
function checkBundleCompleteness(files) {
|
|
2904
2912
|
const uploadingFootage = FOOTAGE_FIELDS.some((option) => Boolean(files[option]));
|
|
2905
2913
|
const missingFrom = (specs) => uploadingFootage ? specs.filter((spec) => !files[spec.option]).map((spec) => spec.file) : [];
|
|
2914
|
+
const plateWarnings = [];
|
|
2915
|
+
if (files.plateBackground && !files.plate) {
|
|
2916
|
+
plateWarnings.push("plate.background.png without plate.png — the background is the parallax layer OF a plate; pass --plate (or drop it in the --dir) too");
|
|
2917
|
+
}
|
|
2906
2918
|
return {
|
|
2907
2919
|
missingAdvisory: missingFrom(RERENDER_ADVISORY_FIELDS),
|
|
2908
2920
|
missingContract: missingFrom(RERENDER_CONTRACT_FIELDS),
|
|
2921
|
+
plateWarnings,
|
|
2909
2922
|
uploadingFootage
|
|
2910
2923
|
};
|
|
2911
2924
|
}
|
|
@@ -2922,6 +2935,9 @@ async function trackVideoCommand(idOrLogId, files, onProgress, options = {}) {
|
|
|
2922
2935
|
onProgress?.(`warning: ${missing} missing (provenance/eval only) — shipping without it`);
|
|
2923
2936
|
}
|
|
2924
2937
|
}
|
|
2938
|
+
for (const warning of completeness.plateWarnings) {
|
|
2939
|
+
onProgress?.(`warning: ${warning}`);
|
|
2940
|
+
}
|
|
2925
2941
|
const present = VIDEO_FIELDS.map((spec) => ({
|
|
2926
2942
|
field: spec.field,
|
|
2927
2943
|
path: files[spec.option]
|
|
@@ -2929,6 +2945,7 @@ async function trackVideoCommand(idOrLogId, files, onProgress, options = {}) {
|
|
|
2929
2945
|
if (present.length === 0) {
|
|
2930
2946
|
throw new CliError2("nothing_to_upload", "No bundle files resolved to upload (pass --dir <bundle> or explicit file flags).");
|
|
2931
2947
|
}
|
|
2948
|
+
const platesOnly = isPlatesOnlyUpload(files);
|
|
2932
2949
|
const presign = await adminApiPost(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/video/uploads`, { fields: present.map((spec) => spec.field) });
|
|
2933
2950
|
const byField = new Map(presign.uploads.map((upload) => [upload.field, upload]));
|
|
2934
2951
|
const urls = {};
|
|
@@ -2949,6 +2966,10 @@ async function trackVideoCommand(idOrLogId, files, onProgress, options = {}) {
|
|
|
2949
2966
|
}
|
|
2950
2967
|
urls[spec.field] = `${FOUND_BASE}/${upload.key}`;
|
|
2951
2968
|
}
|
|
2969
|
+
if (platesOnly) {
|
|
2970
|
+
onProgress?.(`plate pre-upload complete — compose against ${FOUND_BASE}/${presign.logId}/plate.png; finalize is deferred to the footage ship`);
|
|
2971
|
+
return { logId: presign.logId, ok: true, trackId: presign.trackId, urls };
|
|
2972
|
+
}
|
|
2952
2973
|
const manifest = files.render ? await readManifestFields(files.render) : {};
|
|
2953
2974
|
const videoModel = files.model?.trim().slice(0, 120) || manifest.model || DEFAULT_VIDEO_MODEL;
|
|
2954
2975
|
const videoModelReasoning = files.reasoning?.trim().slice(0, 120) || manifest.reasoning || DEFAULT_VIDEO_REASONING;
|
|
@@ -3058,7 +3079,7 @@ async function trackNoteCommand(idOrLogId, options) {
|
|
|
3058
3079
|
const body = { note: options.note };
|
|
3059
3080
|
return adminApiPost(`/api/admin/tracks/${encodeURIComponent(idOrLogId)}/note`, body);
|
|
3060
3081
|
}
|
|
3061
|
-
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;
|
|
3082
|
+
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;
|
|
3062
3083
|
var init_track = __esm(() => {
|
|
3063
3084
|
init_api();
|
|
3064
3085
|
init_output();
|
|
@@ -3070,6 +3091,8 @@ var init_track = __esm(() => {
|
|
|
3070
3091
|
{ field: "footage-landscape-social", option: "footageLandscapeSocial" },
|
|
3071
3092
|
{ field: "poster", option: "poster" },
|
|
3072
3093
|
{ field: "cover", option: "cover" },
|
|
3094
|
+
{ field: "plate", option: "plate" },
|
|
3095
|
+
{ field: "plate-background", option: "plateBackground" },
|
|
3073
3096
|
{ field: "note", option: "note" },
|
|
3074
3097
|
{ field: "composition", option: "composition" },
|
|
3075
3098
|
{ field: "props", option: "props" },
|
|
@@ -3095,6 +3118,8 @@ var init_track = __esm(() => {
|
|
|
3095
3118
|
"footageLandscape",
|
|
3096
3119
|
"footageLandscapeSocial"
|
|
3097
3120
|
];
|
|
3121
|
+
PLATE_FIELDS = ["plate", "plateBackground"];
|
|
3122
|
+
NON_FILE_OPTIONS = ["model", "reasoning"];
|
|
3098
3123
|
});
|
|
3099
3124
|
|
|
3100
3125
|
// src/commands/add.ts
|
|
@@ -7272,7 +7297,7 @@ function addAdminCommands(program2) {
|
|
|
7272
7297
|
const { trackUpdateCommand: trackUpdateCommand2 } = await Promise.resolve().then(() => (init_track(), exports_track));
|
|
7273
7298
|
await runTrackUpdate(trackId, options, trackUpdateCommand2);
|
|
7274
7299
|
});
|
|
7275
|
-
adminTrack.command("video").description("Upload a track's video bundle to R2 and link it").argument("[idOrLogId]").option("--allow-partial", "Allow an intentionally partial upload (skip the re-render-contract check; e.g. poster-only)", false).option("--composition <file>", "Composition source file").option("--cover <file>", "Cover image").option("--dir <dir>", "Bundle directory").option("--footage <file>", "Video footage (square crop source)").option("--footage-landscape <file>", "Clean landscape cut (optional escape hatch)").option("--footage-landscape-social <file>", "Landscape cut with baked text (optional)").option("--footage-notext <file>", "Portrait cut without the type layer (optional)").option("--footage-social <file>", "Portrait social cut (baked text)").option("--intent <file>", "Render-intent JSON (optional)").option("--json", "Print JSON", false).option("--metrics <file>", "Gate metrics JSON (optional)").option("--model <model>", "Authoring AI model (<provider>/<model>)").option("--note <file>", "Note file").option("--poster <file>", "Poster image").option("--props <file>", "Render props JSON").option("--reasoning <level>", "Authoring model reasoning effort (e.g. high)").option("--render <file>", "Render metadata JSON").option("--scene <file>", "Scene replay manifest JSON (fluncle.scene/1, optional)").allowExcessArguments().action(async (idOrLogId, options) => {
|
|
7300
|
+
adminTrack.command("video").description("Upload a track's video bundle to R2 and link it").argument("[idOrLogId]").option("--allow-partial", "Allow an intentionally partial upload (skip the re-render-contract check; e.g. poster-only)", false).option("--composition <file>", "Composition source file").option("--cover <file>", "Cover image").option("--dir <dir>", "Bundle directory").option("--footage <file>", "Video footage (square crop source)").option("--footage-landscape <file>", "Clean landscape cut (optional escape hatch)").option("--footage-landscape-social <file>", "Landscape cut with baked text (optional)").option("--footage-notext <file>", "Portrait cut without the type layer (optional)").option("--footage-social <file>", "Portrait social cut (baked text)").option("--intent <file>", "Render-intent JSON (optional)").option("--json", "Print JSON", false).option("--metrics <file>", "Gate metrics JSON (optional)").option("--model <model>", "Authoring AI model (<provider>/<model>)").option("--note <file>", "Note file").option("--plate <file>", "Plate-lane photographic plate (plate.png; uploadable pre-render)").option("--plate-background <file>", "The plate's subject-removed background (plate.background.png, optional)").option("--poster <file>", "Poster image").option("--props <file>", "Render props JSON").option("--reasoning <level>", "Authoring model reasoning effort (e.g. high)").option("--render <file>", "Render metadata JSON").option("--scene <file>", "Scene replay manifest JSON (fluncle.scene/1, optional)").allowExcessArguments().action(async (idOrLogId, options) => {
|
|
7276
7301
|
const { trackVideoCommand: trackVideoCommand2 } = await Promise.resolve().then(() => (init_track(), exports_track));
|
|
7277
7302
|
await runTrackVideo(idOrLogId, options, trackVideoCommand2);
|
|
7278
7303
|
});
|
|
@@ -7697,7 +7722,7 @@ async function runBackfillDiscogs(options, backfillDiscogsCommand2) {
|
|
|
7697
7722
|
}
|
|
7698
7723
|
async function runTrackVideo(idOrLogId, options, trackVideoCommand2) {
|
|
7699
7724
|
if (!idOrLogId) {
|
|
7700
|
-
throw new Error("Missing id. Usage: fluncle admin tracks video <track_id|log_id> (--dir <dir> | --footage <file> [--footage-social <file>] [--footage-notext <file>] [--footage-landscape <file>] [--footage-landscape-social <file>] [--poster <file>] [--cover <file>] [--note <file>] [--composition <file>] [--props <file>] [--render <file>] [--intent <file>] [--metrics <file>] [--scene <file>]) [--allow-partial]");
|
|
7725
|
+
throw new Error("Missing id. Usage: fluncle admin tracks video <track_id|log_id> (--dir <dir> | --footage <file> [--footage-social <file>] [--footage-notext <file>] [--footage-landscape <file>] [--footage-landscape-social <file>] [--poster <file>] [--cover <file>] [--note <file>] [--composition <file>] [--props <file>] [--render <file>] [--intent <file>] [--metrics <file>] [--scene <file>] | --plate <file> [--plate-background <file>]) [--allow-partial]");
|
|
7701
7726
|
}
|
|
7702
7727
|
const dir = options.dir ? path2.resolve(process.cwd(), options.dir) : undefined;
|
|
7703
7728
|
const fromDir = (name) => {
|
|
@@ -7725,14 +7750,17 @@ async function runTrackVideo(idOrLogId, options, trackVideoCommand2) {
|
|
|
7725
7750
|
metrics: resolveFile(options.metrics, "metrics.json"),
|
|
7726
7751
|
model: options.model,
|
|
7727
7752
|
note: resolveFile(options.note, "note.txt"),
|
|
7753
|
+
plate: resolveFile(options.plate, "plate.png"),
|
|
7754
|
+
plateBackground: resolveFile(options.plateBackground, "plate.background.png"),
|
|
7728
7755
|
poster: resolveFile(options.poster, "poster.jpg"),
|
|
7729
7756
|
props: resolveFile(options.props, "props.json"),
|
|
7730
7757
|
reasoning: options.reasoning,
|
|
7731
7758
|
render: resolveFile(options.render, "render.json"),
|
|
7732
7759
|
scene: resolveFile(options.scene, "scene.json")
|
|
7733
7760
|
};
|
|
7734
|
-
|
|
7735
|
-
|
|
7761
|
+
const { isPlatesOnlyUpload: isPlatesOnlyUpload2 } = await Promise.resolve().then(() => (init_track(), exports_track));
|
|
7762
|
+
if (!files.footage && !options.allowPartial && !isPlatesOnlyUpload2(files)) {
|
|
7763
|
+
throw new Error("A footage cut is required (--footage <file>, or --dir containing footage.mp4). Pass --allow-partial for a deliberate partial refresh (e.g. poster-only), or upload plates alone (--plate/--plate-background) for the plate-lane pre-upload.");
|
|
7736
7764
|
}
|
|
7737
7765
|
const onProgress = options.json ? undefined : (message) => console.log(message);
|
|
7738
7766
|
const result = await trackVideoCommand2(idOrLogId, files, onProgress, {
|
|
@@ -8531,6 +8559,8 @@ var stringOptions = new Set([
|
|
|
8531
8559
|
"--metrics",
|
|
8532
8560
|
"--mime",
|
|
8533
8561
|
"--note",
|
|
8562
|
+
"--plate",
|
|
8563
|
+
"--plate-background",
|
|
8534
8564
|
"--platform",
|
|
8535
8565
|
"--poster",
|
|
8536
8566
|
"--props",
|
package/package.json
CHANGED