@aicopycoders/exodus 2026.10.2400-beta.2 → 2026.10.2400-beta.3
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/dist/commands/video.d.ts +6 -0
- package/dist/commands/video.js +43 -9
- package/package.json +1 -1
package/dist/commands/video.d.ts
CHANGED
|
@@ -65,6 +65,11 @@ export interface ClipFinding {
|
|
|
65
65
|
export declare function qcWithoutJudgeWording(qc: ClipQc): ClipQc;
|
|
66
66
|
export declare const NO_TAKE_HISTORY_LINE = "no history recorded for this clip";
|
|
67
67
|
export declare function renderQcTakeHistory(takes: ClipQcTake[] | undefined): string[];
|
|
68
|
+
export interface ReplannedIdea {
|
|
69
|
+
framePrompt?: string;
|
|
70
|
+
videoPrompt?: string;
|
|
71
|
+
imageUrl: string;
|
|
72
|
+
}
|
|
68
73
|
export type ArtifactSubset = {
|
|
69
74
|
type: "storyboard";
|
|
70
75
|
storyboard?: unknown;
|
|
@@ -100,6 +105,7 @@ export type ArtifactSubset = {
|
|
|
100
105
|
voiceFirstBlockedBy?: string[];
|
|
101
106
|
voicePitchHz?: number;
|
|
102
107
|
voicePitchMethod?: string;
|
|
108
|
+
replannedIdea?: ReplannedIdea;
|
|
103
109
|
} | {
|
|
104
110
|
type: "audio";
|
|
105
111
|
sceneIndex?: number;
|
package/dist/commands/video.js
CHANGED
|
@@ -747,6 +747,7 @@ function clipFromArtifact(sceneIndex, artifact) {
|
|
|
747
747
|
voiceFirstBlockedBy: artifact.voiceFirstBlockedBy ?? null,
|
|
748
748
|
voicePitchHz: artifact.voicePitchHz ?? null,
|
|
749
749
|
voicePitchMethod: artifact.voicePitchMethod ?? null,
|
|
750
|
+
replannedIdea: artifact.replannedIdea ?? null,
|
|
750
751
|
};
|
|
751
752
|
}
|
|
752
753
|
function keyframeDownload(sceneIndex, imageUrl) {
|
|
@@ -903,23 +904,37 @@ function isNarrationMaster(artifact) {
|
|
|
903
904
|
artifact.sceneIndex === undefined &&
|
|
904
905
|
Array.isArray(artifact.narration?.cuts));
|
|
905
906
|
}
|
|
907
|
+
function withoutLookRider(prompt) {
|
|
908
|
+
return prompt.replace(/\n\nCUTAWAY STYLE: [\s\S]*$/, "");
|
|
909
|
+
}
|
|
910
|
+
function withReplannedPrompts(raw, replanned) {
|
|
911
|
+
let board;
|
|
912
|
+
try {
|
|
913
|
+
board = JSON.parse(raw);
|
|
914
|
+
}
|
|
915
|
+
catch {
|
|
916
|
+
return raw;
|
|
917
|
+
}
|
|
918
|
+
if (!Array.isArray(board.scenes))
|
|
919
|
+
return raw;
|
|
920
|
+
const scenes = board.scenes.map((scene) => {
|
|
921
|
+
const idea = typeof scene.sceneIndex === "number" ? replanned.get(scene.sceneIndex) : undefined;
|
|
922
|
+
return idea ? { ...scene, ...idea } : scene;
|
|
923
|
+
});
|
|
924
|
+
return JSON.stringify({ ...board, scenes }, null, 2);
|
|
925
|
+
}
|
|
906
926
|
export function planPull(run, items, opts) {
|
|
907
927
|
const texts = [];
|
|
908
928
|
const storyboardArtifact = run.nodes
|
|
909
929
|
.flatMap((n) => n.outputs ?? [])
|
|
910
930
|
.find((a) => a.type === "storyboard");
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
const raw = typeof storyboardArtifact.storyboardJson === "string"
|
|
931
|
+
const storyboardRaw = storyboardArtifact
|
|
932
|
+
? typeof storyboardArtifact.storyboardJson === "string"
|
|
914
933
|
? storyboardArtifact.storyboardJson
|
|
915
934
|
: storyboardArtifact.storyboard !== undefined
|
|
916
935
|
? JSON.stringify(storyboardArtifact.storyboard, null, 2)
|
|
917
|
-
: undefined
|
|
918
|
-
|
|
919
|
-
storyboard = "storyboard.json";
|
|
920
|
-
texts.push({ file: storyboard, body: raw.endsWith("\n") ? raw : `${raw}\n` });
|
|
921
|
-
}
|
|
922
|
-
}
|
|
936
|
+
: undefined
|
|
937
|
+
: undefined;
|
|
923
938
|
let reference = null;
|
|
924
939
|
let productSheet = null;
|
|
925
940
|
let setPlate = null;
|
|
@@ -1056,6 +1071,21 @@ export function planPull(run, items, opts) {
|
|
|
1056
1071
|
const pendingRedo = scenesBeingRedone(run, items);
|
|
1057
1072
|
for (const sceneIndex of pendingRedo)
|
|
1058
1073
|
clipByScene.delete(sceneIndex);
|
|
1074
|
+
const replanned = new Map();
|
|
1075
|
+
for (const [sceneIndex, clip] of clipByScene) {
|
|
1076
|
+
if (!clip.replannedIdea)
|
|
1077
|
+
continue;
|
|
1078
|
+
const { imageUrl, framePrompt, videoPrompt } = clip.replannedIdea;
|
|
1079
|
+
keyframeByScene.set(sceneIndex, keyframeDownload(sceneIndex, imageUrl));
|
|
1080
|
+
if (framePrompt && videoPrompt)
|
|
1081
|
+
replanned.set(sceneIndex, { framePrompt, videoPrompt });
|
|
1082
|
+
}
|
|
1083
|
+
let storyboard = null;
|
|
1084
|
+
if (storyboardRaw !== undefined) {
|
|
1085
|
+
const body = replanned.size > 0 ? withReplannedPrompts(storyboardRaw, replanned) : storyboardRaw;
|
|
1086
|
+
storyboard = "storyboard.json";
|
|
1087
|
+
texts.unshift({ file: storyboard, body: body.endsWith("\n") ? body : `${body}\n` });
|
|
1088
|
+
}
|
|
1059
1089
|
const sceneIndexes = [
|
|
1060
1090
|
...new Set([
|
|
1061
1091
|
...clipByScene.keys(),
|
|
@@ -2201,6 +2231,10 @@ export async function statusFlow(runId, json, deps) {
|
|
|
2201
2231
|
}
|
|
2202
2232
|
if (row.clip?.error)
|
|
2203
2233
|
lines.push(` ${row.clip.error}`);
|
|
2234
|
+
const usedIdea = row.clip?.artifact?.type === "video" ? row.clip.artifact.replannedIdea : undefined;
|
|
2235
|
+
if (usedIdea?.framePrompt) {
|
|
2236
|
+
lines.push(` clip: made from a new idea instead of the approved one. It shows: ${withoutLookRider(usedIdea.framePrompt)}`);
|
|
2237
|
+
}
|
|
2204
2238
|
if (revoicedByScene.has(sceneIndex))
|
|
2205
2239
|
lines.push(" voice: cast voice applied");
|
|
2206
2240
|
if (voiceFirstByScene.has(sceneIndex))
|