@nodaro/prompts 1.51.0 → 1.53.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/dist/{chunk-M6EXNY42.cjs → chunk-EKRO42T3.cjs} +21 -7
- package/dist/chunk-EKRO42T3.cjs.map +1 -0
- package/dist/{chunk-T4TZY5ST.js → chunk-PHCYQWJP.js} +32 -2
- package/dist/chunk-PHCYQWJP.js.map +1 -0
- package/dist/{chunk-HETYHGGW.js → chunk-XR7RAHZI.js} +21 -7
- package/dist/chunk-XR7RAHZI.js.map +1 -0
- package/dist/{chunk-RPGJTLLF.cjs → chunk-XRCK3BCF.cjs} +32 -2
- package/dist/chunk-XRCK3BCF.cjs.map +1 -0
- package/dist/entries/assembly.cjs +24 -24
- package/dist/entries/assembly.d.cts +21 -6
- package/dist/entries/assembly.d.ts +21 -6
- package/dist/entries/assembly.js +1 -1
- package/dist/entries/doctrine.cjs +46 -46
- package/dist/entries/doctrine.js +1 -1
- package/dist/index.cjs +70 -70
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/package.json +2 -2
- package/src/__tests__/frame-reference-slots.test.ts +16 -0
- package/src/frame-reference-slots.ts +4 -4
- package/src/prompt-wizard-categories.ts +2 -0
- package/src/provider-prompt-doctrine.ts +29 -0
- package/src/ref-binding.ts +44 -7
- package/src/video-reference-resolver.ts +1 -1
- package/dist/chunk-HETYHGGW.js.map +0 -1
- package/dist/chunk-M6EXNY42.cjs.map +0 -1
- package/dist/chunk-RPGJTLLF.cjs.map +0 -1
- package/dist/chunk-T4TZY5ST.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -2,13 +2,13 @@ export { BODY_CAPTIONS_PRESET_ID, BRAND_PRESETS, BRAND_PRESET_IDS, BRAND_PRESET_
|
|
|
2
2
|
export { readDirectionFields, readStructuredFields, readSubjectFields } from './chunk-ZRORO6OM.js';
|
|
3
3
|
export { TEXT_REQUIRED_NODE_TYPES, WIRED_OUTPUT_NODE_TYPES, computeAiWriterInput, computeNodeSendText, stripAudioTags } from './chunk-YS6HOWMW.js';
|
|
4
4
|
export { NODE_PROMPT_CANDIDATE_FIELDS, NODE_PROMPT_FIELDS, PROMPT_AFFIX_CORE_FIELD_OVERRIDES, PROMPT_AFFIX_NODE_TYPES, applyPromptAffixes, composeNegative, computeLlmChatFields, computeNodePrompt, computeScriptTopic, getPromptFields, getSnippetMedia, joinPromptParts, nodeHasInlinePrompt, nodeHasPromptField, nodeSupportsPromptAffixes, promptAffixCoreField, promptFieldCarriesAffixes, promptPartSeparator, resolvePrompt } from './chunk-N6VMPG5S.js';
|
|
5
|
-
export { REF_BINDING, SEEDANCE_VIDEO_EDIT_PREFIX, appendField, appendMusicMeta, assembleImageInput, assembleSunoInput, buildSeedanceVideoEditPrompt, buildSurroundFillPrompt, composeSoundHintFromConnections, composeVideoPromptText, getEffectiveSunoCustomMode, identityRefsSentence, imageBindingFor, placeFramesAfterReferences, planFrameDelivery, promptBindsFirstFrame, resolveGeminiOmniI2vInputs, resolveRefIdTokens, resolveReferenceTokens, resolveSeedance2Inputs, resolveVeoI2vInputs, resolveVideoReferenceCore, truncateForField } from './chunk-
|
|
5
|
+
export { REF_BINDING, SEEDANCE_VIDEO_EDIT_PREFIX, appendField, appendMusicMeta, assembleImageInput, assembleSunoInput, buildSeedanceVideoEditPrompt, buildSurroundFillPrompt, composeSoundHintFromConnections, composeVideoPromptText, getEffectiveSunoCustomMode, identityRefsSentence, imageBindingFor, placeFramesAfterReferences, planFrameDelivery, promptBindsFirstFrame, resolveGeminiOmniI2vInputs, resolveRefIdTokens, resolveReferenceTokens, resolveSeedance2Inputs, resolveVeoI2vInputs, resolveVideoReferenceCore, truncateForField } from './chunk-XR7RAHZI.js';
|
|
6
6
|
export { ANGLE_LABELS, ASPECT_RATIO_LABELS, MAX_SUBJECT_KEYS, MOVEMENT_LABELS, SCENE_PROMPT_MAX_LENGTH, SHOT_LABELS, STYLE_SECTION_GAP, STYLE_SECTION_HEADER, SUBJECT_ARRAY_CEILING, SUBJECT_CUSTOM_AGE_KEY, SUBJECT_FIELDS, SUBJECT_FOLD_KEYS, SUBJECT_ID_MAX_CHARS, SUBJECT_IMAGE_HINT_MODE_DEFAULT, SUBJECT_KEYS, SUBJECT_KEY_MAX_CHARS, SUBJECT_VIDEO_HINT_MODE_DEFAULT, appendReferenceLines, applyReferenceOrderToVideo, asBodyClauses, buildIdentityDirectives, buildImagePrompt, buildImagePromptSegments, buildImagePromptWithOverflow, buildReferenceBlocks, buildScenePrompt, composeSectionedPrompt, endsInsideStyleSection, expandImagePositionRefs, expandImageRefTokens, getRegisteredSubjectKeys, insertBeforeStyleSection, normalizeSubjectFields, partitionStyleClauses, referenceDescriptionLine, renderDescribedReferenceLines, renderReferenceCaptionLines, renderStructuredFields, renderStyleSection, renderSubjectHints, resolveCharacterMentions, resolveLocationMentions, sectionedClauseCosts, splitStyleSection, styleSectionFromClauses, styleSlotFor, subjectFieldsForSurface, truncateText } from './chunk-YAIPYPMM.js';
|
|
7
7
|
import './chunk-GILUVQQJ.js';
|
|
8
8
|
export { keepableDirectionHints } from './chunk-JZOPMVGY.js';
|
|
9
9
|
export { PROMPT_HINT_SEPARATOR, joinPromptHints } from './chunk-35UHMDGS.js';
|
|
10
10
|
export { computePackSidecarCoverage } from './chunk-FDOG7BNB.js';
|
|
11
|
-
export { AD_CREATIVE_ANALYSIS_FIELDS, AD_CREATIVE_ANALYSIS_SYSTEM_PROMPT, AUDIO_WIZARD_CATEGORIES, DEFAULT_OWN_MOTION, IMAGE_REFERENCE_PROMPT_DOCTRINE, IMAGE_WIZARD_CATEGORIES, LLM_CHAT_WIZARD_CATEGORIES, MUSIC_WIZARD_CATEGORIES, OWN_MOTION_NODE_TYPES, POST_CONTENT_ANALYSIS_SYSTEM_PROMPT, PROVIDER_CAPABILITIES, PROVIDER_PROMPT_DOCTRINES, REFERENCE_IMAGE_ROLES, SCENE3D_FIGURE_REFERENCE_RULE, SCENE3D_FREE_PLATE_SLOTS, SCENE3D_LAYOUT_REFERENCE_SCOPING_FIXTURE, SCENE3D_LAYOUT_REFERENCE_SCOPING_LINE, SCENE3D_LAYOUT_SCOPING_FOR, SCENE3D_LAYOUT_SCOPING_IGNORE, SCENE3D_LAYOUT_SCOPING_LOOK_SOURCE, SCENE3D_LAYOUT_SCOPING_MARKER, SCENE3D_UNREFERENCED_FIGURES_WARNING_CODE, TEXT_WIZARD_CATEGORIES, VIDEO_WIZARD_CATEGORIES, appendScene3DStillScopingLines, buildAdCreativeAnalysisUserText, buildCharacterPrompt, buildCreaturePrompt, buildFaceTemplateInputs, buildLocationMotionPrompt, buildLocationPrompt, buildLocationRefinePrompt, buildMotionPrompt, buildObjectMotionPrompt, buildObjectPrompt, buildScene3DLayoutScopingLine, buildScene3DUnreferencedFiguresWarning, getCategoriesForNodeType, getPromptDoctrine, getPromptTips, hasScene3DLayoutScopingLine, isWizardSupported, ownMotionHint, renderScene3DLayoutScopingLine, scene3DLayoutVideoCaptions } from './chunk-
|
|
11
|
+
export { AD_CREATIVE_ANALYSIS_FIELDS, AD_CREATIVE_ANALYSIS_SYSTEM_PROMPT, AUDIO_WIZARD_CATEGORIES, DEFAULT_OWN_MOTION, IMAGE_REFERENCE_PROMPT_DOCTRINE, IMAGE_WIZARD_CATEGORIES, LLM_CHAT_WIZARD_CATEGORIES, MUSIC_WIZARD_CATEGORIES, OWN_MOTION_NODE_TYPES, POST_CONTENT_ANALYSIS_SYSTEM_PROMPT, PROVIDER_CAPABILITIES, PROVIDER_PROMPT_DOCTRINES, REFERENCE_IMAGE_ROLES, SCENE3D_FIGURE_REFERENCE_RULE, SCENE3D_FREE_PLATE_SLOTS, SCENE3D_LAYOUT_REFERENCE_SCOPING_FIXTURE, SCENE3D_LAYOUT_REFERENCE_SCOPING_LINE, SCENE3D_LAYOUT_SCOPING_FOR, SCENE3D_LAYOUT_SCOPING_IGNORE, SCENE3D_LAYOUT_SCOPING_LOOK_SOURCE, SCENE3D_LAYOUT_SCOPING_MARKER, SCENE3D_UNREFERENCED_FIGURES_WARNING_CODE, TEXT_WIZARD_CATEGORIES, VIDEO_WIZARD_CATEGORIES, appendScene3DStillScopingLines, buildAdCreativeAnalysisUserText, buildCharacterPrompt, buildCreaturePrompt, buildFaceTemplateInputs, buildLocationMotionPrompt, buildLocationPrompt, buildLocationRefinePrompt, buildMotionPrompt, buildObjectMotionPrompt, buildObjectPrompt, buildScene3DLayoutScopingLine, buildScene3DUnreferencedFiguresWarning, getCategoriesForNodeType, getPromptDoctrine, getPromptTips, hasScene3DLayoutScopingLine, isWizardSupported, ownMotionHint, renderScene3DLayoutScopingLine, scene3DLayoutVideoCaptions } from './chunk-PHCYQWJP.js';
|
|
12
12
|
export { CINEMATIC_LOOK_TAIL, FILM_STILL_PREFIX, NEUTRAL_PERSON, REALISM_FINISH, REALISM_PASS_INSTRUCTION, REALISM_SKIN, REFERENCE_RULES, REFERENCE_RULES_MULTI_PERSON, SCENE_FRAME_RULE, filmStillPrefix, realismEmptyHands, realismViewpoint, referenceRulesBlock } from './chunk-T64D26P4.js';
|
|
13
13
|
export { DEFAULT_IDENTITY_LOCK, DEFAULT_TEMPLATES, applyTemplate, buildIdentityLockLine, characterLockToRefLock, collectIdentityLockClause, getIdentityLockClause, hasUpstreamCharacter, resolveTemplate, toIdentityLockMode, withForcedIdentityLock } from './chunk-BQWIPLLR.js';
|
|
14
14
|
import './chunk-ADMHDFHB.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nodaro/prompts",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.53.0",
|
|
4
4
|
"description": "Nodaro's prompt-engineering layer — person/picker catalogs with prompt hints, identity-lock clauses, entity prompt builders, brand presets, and prompt/reference assembly shared by the Nodaro platform and SDK.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "FSL-1.1-Apache-2.0",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"test": "vitest run"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"@nodaro/shared": "^3.
|
|
73
|
+
"@nodaro/shared": "^3.58.0"
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
76
|
"tsup": "^8.5.0",
|
|
@@ -30,6 +30,22 @@ describe("placeFramesAfterReferences", () => {
|
|
|
30
30
|
)
|
|
31
31
|
})
|
|
32
32
|
|
|
33
|
+
it("writes plain `image N` sentences that say what each image is", () => {
|
|
34
|
+
const start = placeFramesAfterReferences({ firstFrameUrl: "F", refImageUrls: R(2), imageCap: 6, syntax: "image N", bindIdentities: true })
|
|
35
|
+
expect(start.promptSuffix).toBe(
|
|
36
|
+
"image 3 is the opening (first) frame of the video. image 1 and image 2 are references for the subject; they are not frames.",
|
|
37
|
+
)
|
|
38
|
+
const both = placeFramesAfterReferences({ firstFrameUrl: "F", lastFrameUrl: "L", refImageUrls: R(3), imageCap: 6, syntax: "image N", bindIdentities: true })
|
|
39
|
+
expect(both.promptSuffix).toBe(
|
|
40
|
+
"image 4 is the opening (first) frame and image 5 is the closing (last) frame of the video. image 1, image 2 and image 3 are references for the subject; they are not frames.",
|
|
41
|
+
)
|
|
42
|
+
const one = placeFramesAfterReferences({ lastFrameUrl: "L", refImageUrls: R(1), imageCap: 6, syntax: "image N", bindIdentities: true })
|
|
43
|
+
expect(one.promptSuffix).toBe("image 2 is the closing (last) frame of the video. image 1 is a reference for the subject; it is not a frame.")
|
|
44
|
+
// Never the platform's `@image_N` duplicate check: a prompt carrying it is not this syntax's binding.
|
|
45
|
+
const prompted = placeFramesAfterReferences({ prompt: "use @image_2 as the first frame", firstFrameUrl: "F", refImageUrls: R(1), imageCap: 6, syntax: "image N" })
|
|
46
|
+
expect(prompted.promptSuffix).toBe("image 2 is the opening (first) frame of the video.")
|
|
47
|
+
})
|
|
48
|
+
|
|
33
49
|
it("skips the opening sentence when the prompt already binds it (@image_N form)", () => {
|
|
34
50
|
const r = placeFramesAfterReferences({ prompt: "use @image_2 as the first frame", firstFrameUrl: "F", refImageUrls: R(1), imageCap: 9 })
|
|
35
51
|
expect(r.promptSuffix).toBe("")
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { imageBindingFor, type ImageReferenceSyntax } from "./ref-binding.js"
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* WHERE A START / END FRAME GOES WHEN IT SHARES A MODEL'S REFERENCE LIST — the
|
|
@@ -29,7 +29,7 @@ export interface FrameReferenceSlotsArgs {
|
|
|
29
29
|
/** The provider's image cap — frames and references together. */
|
|
30
30
|
imageCap: number
|
|
31
31
|
/** The provider's reference syntax (`videoProviderReferenceSyntax`). */
|
|
32
|
-
syntax?:
|
|
32
|
+
syntax?: ImageReferenceSyntax
|
|
33
33
|
bindIdentities?: boolean
|
|
34
34
|
}
|
|
35
35
|
|
|
@@ -65,14 +65,14 @@ export function placeFramesAfterReferences(args: FrameReferenceSlotsArgs): Frame
|
|
|
65
65
|
if (promptBindsStart && firstFrameOrdinal > 0 && lastFrameOrdinal === 0) {
|
|
66
66
|
// The prompt already binds the first frame at its own (working) position.
|
|
67
67
|
} else if (firstFrameOrdinal > 0 && lastFrameOrdinal > 0) {
|
|
68
|
-
frameSentence =
|
|
68
|
+
frameSentence = binding.frames(firstFrameOrdinal, lastFrameOrdinal)
|
|
69
69
|
} else if (firstFrameOrdinal > 0) {
|
|
70
70
|
frameSentence = binding.frame(firstFrameOrdinal, "opening")
|
|
71
71
|
} else if (lastFrameOrdinal > 0) {
|
|
72
72
|
frameSentence = binding.frame(lastFrameOrdinal, "closing")
|
|
73
73
|
}
|
|
74
74
|
const identitySentence = args.bindIdentities && kept.length > 0 && frameCount > 0
|
|
75
|
-
?
|
|
75
|
+
? binding.identities(1, kept.length)
|
|
76
76
|
: ""
|
|
77
77
|
const promptSuffix = [frameSentence, identitySentence].filter(Boolean).join(" ")
|
|
78
78
|
return { imageUrls, promptSuffix, droppedRefImages, firstFrameOrdinal, lastFrameOrdinal }
|
|
@@ -273,6 +273,7 @@ export const PROVIDER_CAPABILITIES: Record<string, Record<string, string>> = {
|
|
|
273
273
|
"ltx-2.3-fast": "Lightricks LTX 2.3 Fast — text/image→video, 6–20s, up to 4K",
|
|
274
274
|
"gemini-omni-video": "Google Gemini Omni — multimodal video with native audio, 4–10s, up to 4K.",
|
|
275
275
|
"gemini-omni-flash": "Google Gemini Omni Flash — faster, cheaper Omni tier; multimodal video with native audio, 4–10s, up to 4K.",
|
|
276
|
+
"gemini-omni-flash-1-2": "Google Gemini Omni Flash 1.2 — video with native audio, 3–15s, 360p to 4K; text, up to 6 reference images, exact first and last frames, or a video edit.",
|
|
276
277
|
"wan-3": "Wan 3.0 — multimodal refs (10 images / 5 videos / 5 audio) or first+last frame, native audio, 2–30s, 480p/720p/1080p",
|
|
277
278
|
"wan-3-prime": "Wan 3.0 Prime — high-speed Wan 3.0 tier; same surface, faster turnaround at a higher rate",
|
|
278
279
|
"vidu-q4": "Vidu Q4 — start frame or up to 15 reference images + 3 MP3 audio refs, native audio, 3–16s, 540p–4K (image required)",
|
|
@@ -311,6 +312,7 @@ export const PROVIDER_CAPABILITIES: Record<string, Record<string, string>> = {
|
|
|
311
312
|
"ltx-2.3-fast": "Lightricks LTX 2.3 Fast — start/end frame i2v, 6–20s, up to 4K",
|
|
312
313
|
"gemini-omni-video": "Google Gemini Omni — multimodal video with native audio, 4–10s, up to 4K.",
|
|
313
314
|
"gemini-omni-flash": "Google Gemini Omni Flash — faster, cheaper Omni tier; multimodal video with native audio, 4–10s, up to 4K.",
|
|
315
|
+
"gemini-omni-flash-1-2": "Google Gemini Omni Flash 1.2 — video with native audio, 3–15s, 360p to 4K; text, up to 6 reference images, exact first and last frames, or a video edit.",
|
|
314
316
|
"wan-3": "Wan 3.0 — multimodal refs (10 images / 5 videos / 5 audio) or first+last frame, native audio, 2–30s, 480p/720p/1080p",
|
|
315
317
|
"wan-3-prime": "Wan 3.0 Prime — high-speed Wan 3.0 tier; same surface, faster turnaround at a higher rate",
|
|
316
318
|
"vidu-q4": "Vidu Q4 — animate a start frame, or direct up to 15 reference images + 3 MP3 audio refs; native audio, 3–16s, 540p–4K",
|
|
@@ -268,6 +268,34 @@ Source: KIE gemini-omni-video market contract (parameters + live behavior probed
|
|
|
268
268
|
aspect-ratio hard-reject, see providers/kie/video.ts). Captured 2026-08-09.`,
|
|
269
269
|
}
|
|
270
270
|
|
|
271
|
+
const GEMINI_OMNI_12_DOCTRINE: ProviderPromptDoctrine = {
|
|
272
|
+
providers: ["gemini-omni-flash-1-2"],
|
|
273
|
+
heading: "Gemini Omni Flash 1.2 (gemini-omni-flash-1-2)",
|
|
274
|
+
tips: [
|
|
275
|
+
"Google video with native sound: text-to-video, frames, reference images and video-edit through one prompt surface. Every second from 3 to 15; 360p, 720p, 1080p or 4K.",
|
|
276
|
+
"Structure like the platform default: subject → action → scene → lighting → camera → style. Quote dialogue lines to have them spoken; describe SFX and ambience plainly.",
|
|
277
|
+
"Only a start frame (and an end frame) wired: they are sent as exact first and last frames. With reference images wired too, frames join the image list after your references and are named in the prompt.",
|
|
278
|
+
"Up to 6 reference images: bind them by ordinal ('the woman from @image_1'). No character or voice references on this model. Video-edit: describe the change; the output follows the source clip, up to 15s.",
|
|
279
|
+
],
|
|
280
|
+
doctrine: `Prompt structure (no public Google prompt guide exists for this endpoint — the API
|
|
281
|
+
contract is the doctrine source):
|
|
282
|
+
subject → action → scene/environment → lighting → camera movement → style → constraints.
|
|
283
|
+
|
|
284
|
+
**Modes (picked from the wired inputs)**
|
|
285
|
+
- Nothing visual → text-to-video.
|
|
286
|
+
- Start frame alone, or start + end frame → exact frames. First + last holds up to 10s; past that the two frames go by the reference route below.
|
|
287
|
+
- Reference images wired → your images come FIRST, in your order (\`@image_1\`, \`@image_2\`, …), up to 6. A wired start or end frame is appended after them and the platform names it in the prompt as the opening or closing frame.
|
|
288
|
+
- Source video wired → video-edit: describe the CHANGE, not a full re-description. The output follows the source clip, which is cut to 15s at most. Up to 5 images may ride beside it.
|
|
289
|
+
|
|
290
|
+
**Audio (native)**
|
|
291
|
+
- Audio is generated with the clip. Quote dialogue to have it spoken; describe SFX and ambience plainly. State exclusions ("no music") or a bed may be invented.
|
|
292
|
+
|
|
293
|
+
**Duration & tiers**
|
|
294
|
+
- Any whole second from 3 to 15. 360p is for drafts; 720p and 1080p are close in price; 4K only when the deliverable needs it.
|
|
295
|
+
|
|
296
|
+
Source: KIE google/gemini-omni-flash-1-2 market contract. Captured 2026-11-09.`,
|
|
297
|
+
}
|
|
298
|
+
|
|
271
299
|
const GROK_IMAGINE_DOCTRINE: ProviderPromptDoctrine = {
|
|
272
300
|
providers: ["grok-i2v", "grok-imagine-video-1.5"],
|
|
273
301
|
heading: "Grok Imagine (grok-i2v, grok-imagine-video-1.5)",
|
|
@@ -521,6 +549,7 @@ export const PROVIDER_PROMPT_DOCTRINES: readonly ProviderPromptDoctrine[] = [
|
|
|
521
549
|
MINIMAX_H3_DOCTRINE,
|
|
522
550
|
VEO_31_DOCTRINE,
|
|
523
551
|
GEMINI_OMNI_DOCTRINE,
|
|
552
|
+
GEMINI_OMNI_12_DOCTRINE,
|
|
524
553
|
GROK_IMAGINE_DOCTRINE,
|
|
525
554
|
WAN_DOCTRINE,
|
|
526
555
|
WAN_3_DOCTRINE,
|
package/src/ref-binding.ts
CHANGED
|
@@ -48,24 +48,61 @@ export const REF_BINDING = {
|
|
|
48
48
|
`Use @image_${n} as the ${role} (${role === "opening" ? "first" : "last"}) frame of the video.`,
|
|
49
49
|
} as const
|
|
50
50
|
|
|
51
|
-
/**
|
|
51
|
+
/** How a video provider addresses its images in the prompt, by array order
|
|
52
|
+
* (`VideoReferenceSyntax` in @nodaro/shared). */
|
|
53
|
+
export type ImageReferenceSyntax = "@image_N" | "@image(n)" | "[Image N]" | "image N"
|
|
54
|
+
|
|
55
|
+
/** The binding sentences — frames and identity references — in one provider syntax. */
|
|
52
56
|
export interface ImageBinding {
|
|
53
57
|
ordinal: (n: number) => string
|
|
58
|
+
/** One frame: the opening or the closing one. */
|
|
54
59
|
frame: (n: number, role: "opening" | "closing") => string
|
|
60
|
+
/** A start and an end frame together. */
|
|
61
|
+
frames: (first: number, last: number) => string
|
|
62
|
+
/** Seats `first`..`last` are references, not frames. */
|
|
63
|
+
identities: (first: number, last: number) => string
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const roleWords = (role: "opening" | "closing") => `${role} (${role === "opening" ? "first" : "last"})`
|
|
67
|
+
|
|
68
|
+
/** "image 1", "image 1 and image 2", "image 1, image 2 and image 3". */
|
|
69
|
+
function plainList(first: number, last: number): string {
|
|
70
|
+
const names = Array.from({ length: last - first + 1 }, (_, i) => `image ${first + i}`)
|
|
71
|
+
return names.length === 1 ? names[0] : `${names.slice(0, -1).join(", ")} and ${names[names.length - 1]}`
|
|
55
72
|
}
|
|
56
73
|
|
|
57
74
|
/**
|
|
58
75
|
* The image binding in a provider's OWN reference syntax
|
|
59
76
|
* (`videoProviderReferenceSyntax` in @nodaro/shared). `@image_N` IS
|
|
60
|
-
* {@link REF_BINDING} — the platform swap point, byte for byte;
|
|
61
|
-
* spell the same
|
|
77
|
+
* {@link REF_BINDING} — the platform swap point, byte for byte; `@image(n)` and
|
|
78
|
+
* `[Image N]` spell the same sentences in the form the provider documents.
|
|
79
|
+
*
|
|
80
|
+
* `image N` (Gemini Omni Flash 1.2) is plain words, each sentence stating what
|
|
81
|
+
* an image IS: "image 3 is the opening (first) frame of the video. image 1 and
|
|
82
|
+
* image 2 are references for the subject; they are not frames." It is the form
|
|
83
|
+
* KIE's own example uses. In staging runs neither wording made 1.2 open on the
|
|
84
|
+
* frame: beside references the frame is one more reference, so the sentence
|
|
85
|
+
* guides the clip and never makes the frame exact.
|
|
62
86
|
*/
|
|
63
|
-
export function imageBindingFor(syntax:
|
|
64
|
-
if (syntax === "
|
|
65
|
-
|
|
87
|
+
export function imageBindingFor(syntax: ImageReferenceSyntax): ImageBinding {
|
|
88
|
+
if (syntax === "image N") {
|
|
89
|
+
return {
|
|
90
|
+
ordinal: (n) => `image ${n}`,
|
|
91
|
+
frame: (n, role) => `image ${n} is the ${roleWords(role)} frame of the video.`,
|
|
92
|
+
frames: (first, last) => `image ${first} is the ${roleWords("opening")} frame and image ${last} is the ${roleWords("closing")} frame of the video.`,
|
|
93
|
+
identities: (first, last) => first === last
|
|
94
|
+
? `image ${first} is a reference for the subject; it is not a frame.`
|
|
95
|
+
: `${plainList(first, last)} are references for the subject; they are not frames.`,
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const ordinal = syntax === "@image_N"
|
|
99
|
+
? REF_BINDING.ordinal
|
|
100
|
+
: syntax === "@image(n)" ? (n: number) => `@image(${n})` : (n: number) => `[Image ${n}]`
|
|
66
101
|
return {
|
|
67
102
|
ordinal,
|
|
68
|
-
frame: (n, role) => `Use ${ordinal(n)} as the ${
|
|
103
|
+
frame: syntax === "@image_N" ? REF_BINDING.frame : (n, role) => `Use ${ordinal(n)} as the ${roleWords(role)} frame of the video.`,
|
|
104
|
+
frames: (first, last) => `Use ${ordinal(first)} as the ${roleWords("opening")} frame and ${ordinal(last)} as the ${roleWords("closing")} frame of the video.`,
|
|
105
|
+
identities: (first, last) => identityRefsSentence(first, last, ordinal),
|
|
69
106
|
}
|
|
70
107
|
}
|
|
71
108
|
|
|
@@ -54,7 +54,7 @@ import { tidyReferenceTokenGaps, unboundReferenceTokenText } from "./unbound-ref
|
|
|
54
54
|
// The binding surface string and the id-addressed token resolver live in their
|
|
55
55
|
// own modules (see them for the contracts); re-exported here so every existing
|
|
56
56
|
// importer of this module — and the package index's `export *` — keeps working.
|
|
57
|
-
export { REF_BINDING, identityRefsSentence, imageBindingFor, SEEDANCE_VIDEO_EDIT_PREFIX, buildSeedanceVideoEditPrompt, type ImageBinding } from "./ref-binding.js"
|
|
57
|
+
export { REF_BINDING, identityRefsSentence, imageBindingFor, SEEDANCE_VIDEO_EDIT_PREFIX, buildSeedanceVideoEditPrompt, type ImageBinding, type ImageReferenceSyntax } from "./ref-binding.js"
|
|
58
58
|
export { resolveRefIdTokens, type RefIdTokenContext } from "./ref-id-tokens.js"
|
|
59
59
|
|
|
60
60
|
|