@nodaro/shared 3.11.0 → 3.12.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/index.cjs +2047 -84
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1556 -27
- package/dist/index.d.ts +1556 -27
- package/dist/index.js +1861 -85
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/caption-styles.test.ts +207 -0
- package/src/__tests__/edl-multicam.test.ts +304 -0
- package/src/__tests__/edl.test.ts +822 -0
- package/src/__tests__/fan-out-rows.test.ts +208 -0
- package/src/__tests__/instagram-scrape.test.ts +66 -0
- package/src/__tests__/llm-models.test.ts +48 -11
- package/src/__tests__/meta-ads-scrape.test.ts +284 -0
- package/src/__tests__/node-runtime-keys.test.ts +15 -0
- package/src/__tests__/presentation-utils.test.ts +67 -0
- package/src/__tests__/producer-types.test.ts +19 -0
- package/src/__tests__/schedule-rules.test.ts +265 -0
- package/src/__tests__/speaker-layouts.test.ts +203 -0
- package/src/__tests__/transcribe-capabilities.test.ts +104 -0
- package/src/__tests__/transcribe-preflight.test.ts +60 -0
- package/src/__tests__/trigger-feeds.test.ts +39 -0
- package/src/__tests__/video-duration-auto.test.ts +65 -0
- package/src/__tests__/video-duration.test.ts +56 -0
- package/src/__tests__/video-link.test.ts +137 -0
- package/src/__tests__/workflow-export-strip.test.ts +59 -1
- package/src/caption-styles.ts +240 -0
- package/src/credit-identifiers.ts +31 -0
- package/src/edit-plan-contract.ts +96 -0
- package/src/edl-multicam.ts +185 -0
- package/src/edl.ts +747 -0
- package/src/entity-image-handle.ts +24 -1
- package/src/fan-out-rows.ts +213 -0
- package/src/index.ts +206 -3
- package/src/instagram-scrape.ts +204 -0
- package/src/llm-models.ts +80 -3
- package/src/meta-ads-scrape.ts +463 -0
- package/src/model-catalog.ts +48 -5
- package/src/model-constants.ts +148 -5
- package/src/node-mappable-fields.ts +2 -0
- package/src/node-runtime-keys.ts +28 -0
- package/src/presentation-utils.ts +49 -0
- package/src/producer-types.ts +20 -0
- package/src/schedule-rules.ts +484 -0
- package/src/speaker-layouts.ts +220 -0
- package/src/transcribe-preflight.ts +101 -0
- package/src/trigger-feeds.ts +59 -0
- package/src/trigger-node-types.ts +20 -0
- package/src/video-duration-auto.ts +18 -0
- package/src/video-duration.ts +32 -0
- package/src/video-link.ts +167 -0
- package/src/workflow-export.ts +37 -1
|
@@ -47,12 +47,31 @@ const AGGREGATE_LANE_EFFECTIVE_TYPE: Readonly<Record<string, string>> = {
|
|
|
47
47
|
"out-text": "list",
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Meta Ads scraper: besides its `json` handle it emits the FEATURED ad's
|
|
52
|
+
* copy, creative image and creative video on typed handles. Each behaves as
|
|
53
|
+
* the canonical single-media producer of that type — `text` maps to
|
|
54
|
+
* `combine-text` (ONE string, not a list), so it reaches prompt inputs but
|
|
55
|
+
* not the list consumers.
|
|
56
|
+
*/
|
|
57
|
+
// Shared by every scraper node (Meta Ads, Instagram, …): the typed
|
|
58
|
+
// text / image / video handles emit the canonical single-media producers.
|
|
59
|
+
const SCRAPER_HANDLE_EFFECTIVE_TYPE: Readonly<Record<string, string>> = {
|
|
60
|
+
text: "combine-text",
|
|
61
|
+
image: "upload-image",
|
|
62
|
+
video: "upload-video",
|
|
63
|
+
}
|
|
64
|
+
const SCRAPER_SOURCE_TYPES = new Set(["meta-ads-scrape", "instagram-scrape"])
|
|
65
|
+
|
|
50
66
|
/**
|
|
51
67
|
* The effective output TYPE a given source handle emits. Returns the raw node
|
|
52
68
|
* type for every `(type, handle)` pair EXCEPT:
|
|
53
69
|
* - an entity `image` handle → `"upload-image"` (a plain image producer);
|
|
54
70
|
* - an aggregate (group / collect) lane handle → the plain producer of that
|
|
55
|
-
* lane's media type (see AGGREGATE_LANE_EFFECTIVE_TYPE)
|
|
71
|
+
* lane's media type (see AGGREGATE_LANE_EFFECTIVE_TYPE);
|
|
72
|
+
* - a Meta Ads `text` / `image` / `video` handle → the plain producer of
|
|
73
|
+
* that type (see META_ADS_HANDLE_EFFECTIVE_TYPE); its `json` handle keeps
|
|
74
|
+
* the raw type.
|
|
56
75
|
* Pure — safe for both frontend and backend.
|
|
57
76
|
*/
|
|
58
77
|
export function resolveEffectiveSourceType(
|
|
@@ -66,6 +85,10 @@ export function resolveEffectiveSourceType(
|
|
|
66
85
|
const effective = AGGREGATE_LANE_EFFECTIVE_TYPE[sourceHandleId ?? ""]
|
|
67
86
|
if (effective) return effective
|
|
68
87
|
}
|
|
88
|
+
if (SCRAPER_SOURCE_TYPES.has(rawSourceType ?? "")) {
|
|
89
|
+
const effective = SCRAPER_HANDLE_EFFECTIVE_TYPE[sourceHandleId ?? ""]
|
|
90
|
+
if (effective) return effective
|
|
91
|
+
}
|
|
69
92
|
return rawSourceType ?? ""
|
|
70
93
|
}
|
|
71
94
|
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fan-out pairs by ROW.
|
|
3
|
+
*
|
|
4
|
+
* When several list wires reach one node ("prompt" + "negative" columns of the
|
|
5
|
+
* same List, two Extract Field lists cut from the same JSON array, …) the node
|
|
6
|
+
* runs once per row and every wire contributes the value of THAT row. Both DAG
|
|
7
|
+
* engines (backend orchestrator + in-browser executor) build the plan with the
|
|
8
|
+
* helpers below, so the rules live in exactly one place:
|
|
9
|
+
*
|
|
10
|
+
* - which list drives the fan-out, and which rows run, never depend on the
|
|
11
|
+
* order the wires were drawn in (`resolveListFanOut`);
|
|
12
|
+
* - the driving item is only written into the prompt when its wire actually
|
|
13
|
+
* feeds the prompt (`fanOutTextFeedsPrompt`, `NON_PROMPT_TEXT_LANES`);
|
|
14
|
+
* - an empty cell stays empty IN ITS ROW instead of pulling the rows below it
|
|
15
|
+
* up (`liveRowColumn`, `alignedFieldList`, `compactWithRows`);
|
|
16
|
+
* - an iteration keeps its row when Repeat xN multiplies it (`planFanOut`).
|
|
17
|
+
*/
|
|
18
|
+
import { evaluateJsonPath, stringifyPathResults } from "./json-path.js"
|
|
19
|
+
import { expandItemsWithRepeat } from "./repeat-types.js"
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The text LANES the input resolvers route somewhere OTHER than the prompt slot
|
|
23
|
+
* (`negative` → negativePrompt, `system-prompt` → systemPrompt, an avatar's
|
|
24
|
+
* `script`, an editor's `transcript`, …). A list that drives a fan-out through
|
|
25
|
+
* one of these must NOT also be written into the prompt: the per-row resolution
|
|
26
|
+
* already delivered it where it belongs.
|
|
27
|
+
*
|
|
28
|
+
* Keyed by handle, scoped by node type, because the routers are: `transcript`
|
|
29
|
+
* is the caption track of Add Captions but the very text Forced Alignment
|
|
30
|
+
* aligns. `"*"` = every node type (the router branch is unconditional).
|
|
31
|
+
*
|
|
32
|
+
* DERIVED, not remembered: each engine has a totality test
|
|
33
|
+
* (`fanout-text-handle-totality`) that routes a text source into EVERY input
|
|
34
|
+
* handle of EVERY node type through the real resolver and fails the build on any
|
|
35
|
+
* pair where this table and the router disagree — in either direction. An
|
|
36
|
+
* unlisted lane keeps the old behavior (the item is the prompt), so a miss can
|
|
37
|
+
* only ever reproduce the old bug on that one lane, never a new one.
|
|
38
|
+
*/
|
|
39
|
+
export const NON_PROMPT_TEXT_LANES: Readonly<Record<string, "*" | readonly string[]>> = {
|
|
40
|
+
negative: "*",
|
|
41
|
+
"system-prompt": "*",
|
|
42
|
+
script: ["ai-avatar"],
|
|
43
|
+
transcript: ["add-captions", "apply-edl", "edit-plan"],
|
|
44
|
+
edl: ["apply-edl"],
|
|
45
|
+
silence: ["edit-plan"],
|
|
46
|
+
qrText: ["image-overlay"],
|
|
47
|
+
transition: ["slideshow"],
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Does a TEXT list wired to `targetHandle` of a `nodeType` node feed its prompt slot? */
|
|
51
|
+
export function fanOutTextFeedsPrompt(nodeType: string | null | undefined, targetHandle: string | null | undefined): boolean {
|
|
52
|
+
const scope = Object.hasOwn(NON_PROMPT_TEXT_LANES, targetHandle ?? "") ? NON_PROMPT_TEXT_LANES[targetHandle ?? ""] : undefined
|
|
53
|
+
if (scope === undefined) return true
|
|
54
|
+
return scope !== "*" && !scope.includes(nodeType ?? "")
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const isBlank = (v: unknown): boolean => typeof v !== "string" || v.trim().length === 0
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Drop the empty entries of a row-aligned list, remembering the row every kept
|
|
61
|
+
* value came from. The items are what drives a fan-out (nothing runs for an
|
|
62
|
+
* empty cell); the rows are what keeps the OTHER wires on the same row.
|
|
63
|
+
*/
|
|
64
|
+
export function compactWithRows(aligned: readonly string[]): { items: string[]; rowIndices: number[] } {
|
|
65
|
+
const items: string[] = []
|
|
66
|
+
const rowIndices: number[] = []
|
|
67
|
+
aligned.forEach((value, row) => {
|
|
68
|
+
if (isBlank(value)) return
|
|
69
|
+
items.push(value)
|
|
70
|
+
rowIndices.push(row)
|
|
71
|
+
})
|
|
72
|
+
return { items, rowIndices }
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* One column of a manual List table, row-aligned: a row is dropped only when
|
|
77
|
+
* EVERY cell of it is blank (the trailing empty row the editor keeps), and an
|
|
78
|
+
* empty cell of a row that has content stays in place as "".
|
|
79
|
+
*/
|
|
80
|
+
export function liveRowColumn(rows: ReadonlyArray<ReadonlyArray<string | undefined>>, colIndex: number): string[] {
|
|
81
|
+
return rows
|
|
82
|
+
.filter((row) => row.some((cell) => !isBlank(cell)))
|
|
83
|
+
.map((row) => (typeof row[colIndex] === "string" ? (row[colIndex] as string).trim() : ""))
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** One list wire that could drive a fan-out. */
|
|
87
|
+
export interface FanOutCandidate {
|
|
88
|
+
/** Target handle of the consumer-side wire. */
|
|
89
|
+
targetHandle: string | null | undefined
|
|
90
|
+
/** The wire's values in row order — may hold "" for an empty row. */
|
|
91
|
+
aligned: readonly string[]
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Turn the lists that reach a node into ONE fan-out, so that nothing depends on
|
|
96
|
+
* the order the wires were drawn in. `candidates` are the "each" lists that hold
|
|
97
|
+
* more than one value, in wire order.
|
|
98
|
+
*
|
|
99
|
+
* The PRIMARY is the list that holds the most values (the first of them when
|
|
100
|
+
* several tie): it sets the row space. Both engines get it from here, so the
|
|
101
|
+
* orchestrator and the in-browser executor cannot disagree on how many times a
|
|
102
|
+
* node runs. Lists with the SAME number of rows share that row space — two
|
|
103
|
+
* columns of one table, two Extract Field lists cut from one array — and are
|
|
104
|
+
* settled together:
|
|
105
|
+
*
|
|
106
|
+
* - the DRIVER (its item becomes the per-row override) is a text list that
|
|
107
|
+
* feeds the prompt, when there is one: that item is what must win over the
|
|
108
|
+
* typed prompt, and a list wired to `negative` must never supply it;
|
|
109
|
+
* - a ROW runs when ANY of those lists has a value in it. A row is never
|
|
110
|
+
* dropped because one column is empty there — that column just contributes
|
|
111
|
+
* nothing for the row — and a row with no value anywhere does not run.
|
|
112
|
+
*
|
|
113
|
+
* A list with a different number of rows is not part of this: it keeps
|
|
114
|
+
* wrapping around per iteration, as it always has.
|
|
115
|
+
*/
|
|
116
|
+
export function resolveListFanOut<C extends FanOutCandidate>(
|
|
117
|
+
candidates: readonly C[],
|
|
118
|
+
nodeType: string | null | undefined,
|
|
119
|
+
): ListFanOut | undefined {
|
|
120
|
+
if (candidates.length === 0) return undefined
|
|
121
|
+
const held = (c: C) => compactWithRows(c.aligned).items.length
|
|
122
|
+
const primary = candidates.reduce((best, c) => (held(c) > held(best) ? c : best))
|
|
123
|
+
const space = candidates.filter((c) => c.aligned.length === primary.aligned.length)
|
|
124
|
+
const feedsPrompt = (c: C) => fanOutTextFeedsPrompt(nodeType, c.targetHandle) && isTextList(c.aligned)
|
|
125
|
+
const driver = feedsPrompt(primary) ? primary : (space.find(feedsPrompt) ?? primary)
|
|
126
|
+
const rowIndices: number[] = []
|
|
127
|
+
for (let row = 0; row < primary.aligned.length; row++) {
|
|
128
|
+
if (space.some((c) => !isBlank(c.aligned[row]))) rowIndices.push(row)
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
items: rowIndices.map((row) => (isBlank(driver.aligned[row]) ? "" : driver.aligned[row])),
|
|
132
|
+
rowIndices,
|
|
133
|
+
targetHandle: driver.targetHandle,
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Is this fan-out item a media URL (as opposed to text)? The ONE guess both
|
|
139
|
+
* engines make when a list item has to be applied as an override — kept here so
|
|
140
|
+
* the backend worker and the in-browser executor cannot disagree on it.
|
|
141
|
+
*/
|
|
142
|
+
export function isFanOutUrlItem(item: string): boolean {
|
|
143
|
+
return item.startsWith("http") || /\.(png|jpg|jpeg|webp|gif|mp4|mov|webm|mp3|wav|ogg)(\?|$)/i.test(item)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** A media list never supplies a prompt override, whatever handle it is wired to.
|
|
147
|
+
* The FIRST value decides — a column is one kind of thing; this is not a scan. */
|
|
148
|
+
function isTextList(aligned: readonly string[]): boolean {
|
|
149
|
+
const first = aligned.find((v) => !isBlank(v))
|
|
150
|
+
return first !== undefined && !isFanOutUrlItem(first)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** What a fan-out source resolved to. */
|
|
154
|
+
export interface ListFanOut {
|
|
155
|
+
/** The driving list's value for every row that runs — "" where the driver has
|
|
156
|
+
* none for a row another list keeps alive (nothing is overridden there). */
|
|
157
|
+
items: string[]
|
|
158
|
+
/** `rowIndices[k]` = the row `items[k]` came from, in the driver's row space. */
|
|
159
|
+
rowIndices: number[]
|
|
160
|
+
/** Target handle of the consumer-side wire that drives the fan-out. */
|
|
161
|
+
targetHandle: string | null | undefined
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** The iterations a node will run, in order. */
|
|
165
|
+
export interface FanOutPlan {
|
|
166
|
+
/** One entry per iteration (list items, repeat / provider sentinels). */
|
|
167
|
+
items: string[]
|
|
168
|
+
/** Row each iteration reads its inputs from; undefined when nothing is list-driven. */
|
|
169
|
+
rows: Array<number | undefined>
|
|
170
|
+
/** Handle the driving list is wired to; undefined when nothing is list-driven. */
|
|
171
|
+
targetHandle: string | null | undefined
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Expand a fan-out into its iterations (list x Repeat xN, providers, repeats —
|
|
176
|
+
* `expandItemsWithRepeat` stays the single rule for that) and pin every
|
|
177
|
+
* iteration to the ROW its item came from. Repeat xN runs a row N times: the
|
|
178
|
+
* copies share the row, they do not walk on to the next one.
|
|
179
|
+
*/
|
|
180
|
+
export function planFanOut(
|
|
181
|
+
fanOut: ListFanOut | undefined,
|
|
182
|
+
nodeType: string,
|
|
183
|
+
nodeData: Record<string, unknown>,
|
|
184
|
+
): FanOutPlan | null {
|
|
185
|
+
const items = expandItemsWithRepeat(fanOut?.items, nodeType, nodeData)
|
|
186
|
+
if (!items) return null
|
|
187
|
+
const listDriven = fanOut !== undefined && fanOut.items.length > 1
|
|
188
|
+
if (!listDriven) return { items, rows: items.map(() => undefined), targetHandle: undefined }
|
|
189
|
+
const perRow = items.length / fanOut.items.length
|
|
190
|
+
return {
|
|
191
|
+
items,
|
|
192
|
+
rows: items.map((_, k) => fanOut.rowIndices[Math.floor(k / perRow)]),
|
|
193
|
+
targetHandle: fanOut.targetHandle,
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Extract Field, List output, over a root ARRAY: one entry per element, "" where
|
|
199
|
+
* the element has no value — so two Extract Field lists cut from the same array
|
|
200
|
+
* stay row-aligned. Returns undefined when rows cannot be defined (the root is
|
|
201
|
+
* not an array, an element fans into several values, or no element carries the
|
|
202
|
+
* field at all) — the caller then keeps the plain "values that exist" list.
|
|
203
|
+
*/
|
|
204
|
+
export function alignedFieldList(value: unknown, path: string): string[] | undefined {
|
|
205
|
+
if (!Array.isArray(value) || value.length === 0) return undefined
|
|
206
|
+
const out: string[] = []
|
|
207
|
+
for (const element of value) {
|
|
208
|
+
const found = evaluateJsonPath(element, path)
|
|
209
|
+
if (found.length > 1) return undefined
|
|
210
|
+
out.push(stringifyPathResults(found)[0] ?? "")
|
|
211
|
+
}
|
|
212
|
+
return out.some((v) => v.length > 0) ? out : undefined
|
|
213
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -71,6 +71,10 @@ export {
|
|
|
71
71
|
TEXT_TO_VIDEO_PROVIDERS,
|
|
72
72
|
VIDEO_GEN_PROVIDERS,
|
|
73
73
|
VIDEO_TO_VIDEO_PROVIDERS,
|
|
74
|
+
SEEDANCE_VIDEO_EDIT_PROVIDERS,
|
|
75
|
+
isSeedanceVideoEditProvider,
|
|
76
|
+
VIDEO_TO_VIDEO_NODE_PROVIDERS,
|
|
77
|
+
SEEDANCE_VIDEO_EDIT_SHAPE,
|
|
74
78
|
FACE_SWAP_PROVIDERS,
|
|
75
79
|
VIDEO_UPSCALE_PROVIDERS,
|
|
76
80
|
EXTEND_VIDEO_PROVIDERS,
|
|
@@ -85,6 +89,12 @@ export {
|
|
|
85
89
|
TEXT_TO_AUDIO_PROVIDERS,
|
|
86
90
|
MUSIC_PROVIDERS,
|
|
87
91
|
TRANSCRIBE_PROVIDERS,
|
|
92
|
+
TRANSCRIBE_LANES,
|
|
93
|
+
TRANSCRIBE_PROVIDER_CAPABILITIES,
|
|
94
|
+
transcribeProvidersWithWordTimestamps,
|
|
95
|
+
transcribeLaneSupportsWordTimestamps,
|
|
96
|
+
DEFAULT_TRANSCRIBE_PROVIDER,
|
|
97
|
+
DEFAULT_TRANSCRIBE_NODE_PROVIDER,
|
|
88
98
|
SCRIPT_PROVIDERS,
|
|
89
99
|
AI_WRITER_PROVIDERS,
|
|
90
100
|
QA_CHECK_PROVIDERS,
|
|
@@ -168,6 +178,8 @@ export {
|
|
|
168
178
|
applyDefaultVideoSelection,
|
|
169
179
|
PRICING_DEFAULT_DURATION_SEC,
|
|
170
180
|
pricedOutputDurationSec,
|
|
181
|
+
supportsAutoVideoDuration,
|
|
182
|
+
maxVideoDurationSec,
|
|
171
183
|
PRICING_DEFAULT_RESOLUTION,
|
|
172
184
|
} from "./model-constants.js"
|
|
173
185
|
|
|
@@ -196,6 +208,8 @@ export type {
|
|
|
196
208
|
VideoGenProvider,
|
|
197
209
|
VideoModeAlias,
|
|
198
210
|
VideoToVideoProvider,
|
|
211
|
+
SeedanceVideoEditProvider,
|
|
212
|
+
VideoToVideoNodeProvider,
|
|
199
213
|
VideoUpscaleProvider,
|
|
200
214
|
ExtendVideoProvider,
|
|
201
215
|
FaceSwapProvider,
|
|
@@ -205,6 +219,7 @@ export type {
|
|
|
205
219
|
TextToAudioProvider,
|
|
206
220
|
MusicProvider,
|
|
207
221
|
TranscribeProvider,
|
|
222
|
+
TranscribeLane,
|
|
208
223
|
ScriptProvider,
|
|
209
224
|
AiWriterProvider,
|
|
210
225
|
QaCheckProvider,
|
|
@@ -251,6 +266,7 @@ export {
|
|
|
251
266
|
resolveImageGenCreditIdentifier,
|
|
252
267
|
resolveNormalizedImageGen,
|
|
253
268
|
buildVideoCreditModelIdentifier,
|
|
269
|
+
seedanceVideoEditCreditId,
|
|
254
270
|
pricedVideoSelection,
|
|
255
271
|
buildMotionCreditModelIdentifier,
|
|
256
272
|
sunoCreditType,
|
|
@@ -261,7 +277,7 @@ export {
|
|
|
261
277
|
export type { NormalizedImageGen, PricedVideoSelection } from "./credit-identifiers.js"
|
|
262
278
|
|
|
263
279
|
export * from "./credit-estimators/index.js"
|
|
264
|
-
export { extractVideoDurationFromNode } from "./video-duration.js"
|
|
280
|
+
export { extractVideoDurationFromNode, editPlanSourceDurationSec } from "./video-duration.js"
|
|
265
281
|
|
|
266
282
|
export {
|
|
267
283
|
resolveTopazUpscale,
|
|
@@ -284,6 +300,7 @@ export {
|
|
|
284
300
|
getNodeResult,
|
|
285
301
|
getNodeLabel,
|
|
286
302
|
getInputFieldSchema,
|
|
303
|
+
mergeNodeInputOverrides,
|
|
287
304
|
flattenItems,
|
|
288
305
|
migrateToItems,
|
|
289
306
|
validateNoNestedGroups,
|
|
@@ -357,6 +374,8 @@ export {
|
|
|
357
374
|
ADVANCED_MODE_UNAVAILABLE_REASON,
|
|
358
375
|
motionGraphicsFeature,
|
|
359
376
|
effectiveReasoningEffort,
|
|
377
|
+
REASONING_OUTPUT_FLOOR,
|
|
378
|
+
reasoningOutputFloor,
|
|
360
379
|
type LlmTier,
|
|
361
380
|
type LlmFeature,
|
|
362
381
|
type KieApiFormat,
|
|
@@ -426,6 +445,18 @@ export type {
|
|
|
426
445
|
|
|
427
446
|
export { REPEATABLE_NODE_TYPES, REPEAT_PLACEHOLDER, PROVIDER_PLACEHOLDER_PREFIX, encodeProviderItem, decodeProviderItem, getEffectiveRepeatCount, expandItemsWithRepeat } from "./repeat-types.js"
|
|
428
447
|
|
|
448
|
+
export {
|
|
449
|
+
NON_PROMPT_TEXT_LANES,
|
|
450
|
+
fanOutTextFeedsPrompt,
|
|
451
|
+
isFanOutUrlItem,
|
|
452
|
+
compactWithRows,
|
|
453
|
+
liveRowColumn,
|
|
454
|
+
resolveListFanOut,
|
|
455
|
+
planFanOut,
|
|
456
|
+
alignedFieldList,
|
|
457
|
+
} from "./fan-out-rows.js"
|
|
458
|
+
export type { FanOutCandidate, ListFanOut, FanOutPlan } from "./fan-out-rows.js"
|
|
459
|
+
|
|
429
460
|
export { settledWithLimit } from "./settled-with-limit.js"
|
|
430
461
|
|
|
431
462
|
|
|
@@ -611,6 +642,39 @@ export {
|
|
|
611
642
|
} from "./node-default-mappings.js"
|
|
612
643
|
|
|
613
644
|
export { NODE_MAPPABLE_FIELDS, SUNO_FIELD_HANDLE_FIELDS, fieldKeyFromHandle } from "./node-mappable-fields.js"
|
|
645
|
+
export {
|
|
646
|
+
SCHEDULE_TRIGGER_NODE_TYPE,
|
|
647
|
+
WEBHOOK_TRIGGER_NODE_TYPE,
|
|
648
|
+
TELEGRAM_TRIGGER_NODE_TYPE,
|
|
649
|
+
PROJECTED_TRIGGER_NODE_TYPES,
|
|
650
|
+
isProjectedTriggerNodeType,
|
|
651
|
+
} from "./trigger-node-types.js"
|
|
652
|
+
|
|
653
|
+
export { buildFeedMaps, nodeFeedsAnything, type FeedNode, type FeedEdge, type FeedMaps } from "./trigger-feeds.js"
|
|
654
|
+
|
|
655
|
+
export {
|
|
656
|
+
SCHEDULE_RULE_KINDS,
|
|
657
|
+
SCHEDULE_EVERY_LIMITS,
|
|
658
|
+
isCronExpression,
|
|
659
|
+
isValidTimezone,
|
|
660
|
+
normalizeScheduleRule,
|
|
661
|
+
normalizeScheduleRules,
|
|
662
|
+
legacyScheduleToRules,
|
|
663
|
+
localTimeIn,
|
|
664
|
+
localMinuteKey,
|
|
665
|
+
timezoneOffsetMinutes,
|
|
666
|
+
matchesCronField,
|
|
667
|
+
matchesCron,
|
|
668
|
+
ruleMatches,
|
|
669
|
+
scheduleMatchesAt,
|
|
670
|
+
scheduleOccurrences,
|
|
671
|
+
nextScheduleRuns,
|
|
672
|
+
previewHorizonMs,
|
|
673
|
+
type ScheduleRuleKind,
|
|
674
|
+
type ScheduleRule,
|
|
675
|
+
type ScheduleSpec,
|
|
676
|
+
type LocalTime,
|
|
677
|
+
} from "./schedule-rules.js"
|
|
614
678
|
|
|
615
679
|
|
|
616
680
|
export {
|
|
@@ -622,6 +686,101 @@ export {
|
|
|
622
686
|
type ScraperActorId,
|
|
623
687
|
} from "./scraper-actors.js"
|
|
624
688
|
|
|
689
|
+
export {
|
|
690
|
+
META_ADS_SCRAPE_NODE_TYPE,
|
|
691
|
+
META_ADS_SCRAPE_MODES,
|
|
692
|
+
META_ADS_SCRAPE_PERIODS,
|
|
693
|
+
META_ADS_SCRAPE_STATUSES,
|
|
694
|
+
META_ADS_PLATFORMS,
|
|
695
|
+
isMetaAdsPlatform,
|
|
696
|
+
type MetaAdsPlatform,
|
|
697
|
+
META_ADS_FORMATS,
|
|
698
|
+
isMetaAdsFormat,
|
|
699
|
+
classifyCreativeFormat,
|
|
700
|
+
clampMetaAdsFeaturedIndex,
|
|
701
|
+
featuredMetaAdOutputs,
|
|
702
|
+
type FeaturedMetaAdOutputs,
|
|
703
|
+
type MetaAdsFormat,
|
|
704
|
+
type MetaAdsCreativeFormat,
|
|
705
|
+
META_ADS_SCRAPE_COUNT_OPTIONS,
|
|
706
|
+
META_ADS_SCRAPE_DEFAULT_COUNT,
|
|
707
|
+
META_ADS_SCRAPE_MAX_COUNT,
|
|
708
|
+
META_ADS_SCRAPE_MAX_SOURCES,
|
|
709
|
+
META_ADS_SCRAPE_MAX_QUERY_LENGTH,
|
|
710
|
+
META_ADS_SCRAPE_DEFAULT_COUNTRY,
|
|
711
|
+
META_ADS_SCRAPE_TIERS,
|
|
712
|
+
META_ADS_SCRAPE_CREDIT_COSTS,
|
|
713
|
+
META_ADS_SCRAPE_FALLBACK_CREDIT_ID,
|
|
714
|
+
splitMetaAdsPageUrls,
|
|
715
|
+
isMetaAdsScrapeMode,
|
|
716
|
+
isMetaAdsScrapeCount,
|
|
717
|
+
metaAdsScrapeTier,
|
|
718
|
+
buildMetaAdsScrapeCreditId,
|
|
719
|
+
resolveMetaAdsScrapeCreditId,
|
|
720
|
+
META_ADS_NODE_MODES,
|
|
721
|
+
META_ADS_ADVERTISER_MAX_RESULTS,
|
|
722
|
+
META_ADS_ANALYSIS_TIERS,
|
|
723
|
+
META_ADS_ANALYSIS_CREDITS_PER_AD,
|
|
724
|
+
META_ADS_ANALYSIS_CREDIT_ID,
|
|
725
|
+
META_ADS_ANALYSIS_FOCUS_MAX,
|
|
726
|
+
metaAdsAnalysisCreditId,
|
|
727
|
+
metaAdsAnalysisTier,
|
|
728
|
+
metaAdsAnalysisTierFrom,
|
|
729
|
+
adCreativeAnalysisFrom,
|
|
730
|
+
metaAdsScrapeCreditIdFromNode,
|
|
731
|
+
type MetaAdsAnalysisTier,
|
|
732
|
+
type AdCreativeAnalysis,
|
|
733
|
+
type MetaAdsNodeQuoteFields,
|
|
734
|
+
metaAdsNodeMode,
|
|
735
|
+
isFacebookPageUrl,
|
|
736
|
+
isMetaCdnImageUrl,
|
|
737
|
+
splitMetaAdsAdvertiserNames,
|
|
738
|
+
metaAdsAdvertisersFrom,
|
|
739
|
+
metaAdsScrapeSources,
|
|
740
|
+
metaAdsScrapeWireSources,
|
|
741
|
+
type MetaAdsNodeMode,
|
|
742
|
+
type MetaAdsAdvertiser,
|
|
743
|
+
type MetaAdsNodeSourceFields,
|
|
744
|
+
type MetaAdsWireSources,
|
|
745
|
+
type MetaAdsScrapeMode,
|
|
746
|
+
type MetaAdsScrapePeriod,
|
|
747
|
+
type MetaAdsScrapeStatus,
|
|
748
|
+
type MetaAdsScrapeTier,
|
|
749
|
+
} from "./meta-ads-scrape.js"
|
|
750
|
+
|
|
751
|
+
export {
|
|
752
|
+
INSTAGRAM_SCRAPE_NODE_TYPE,
|
|
753
|
+
INSTAGRAM_SCRAPE_MODES,
|
|
754
|
+
INSTAGRAM_SCRAPE_PERIODS,
|
|
755
|
+
INSTAGRAM_SCRAPE_DEFAULT_COUNT,
|
|
756
|
+
INSTAGRAM_SCRAPE_MAX_COUNT,
|
|
757
|
+
INSTAGRAM_SCRAPE_MAX_SOURCES,
|
|
758
|
+
INSTAGRAM_SCRAPE_MAX_TARGET_LENGTH,
|
|
759
|
+
INSTAGRAM_SCRAPE_TIERS,
|
|
760
|
+
INSTAGRAM_SCRAPE_CREDIT_COSTS,
|
|
761
|
+
INSTAGRAM_SCRAPE_FALLBACK_CREDIT_ID,
|
|
762
|
+
INSTAGRAM_ANALYSIS_CREDIT_ID,
|
|
763
|
+
isInstagramScrapeMode,
|
|
764
|
+
instagramScrapeMode,
|
|
765
|
+
isInstagramScrapeCount,
|
|
766
|
+
instagramScrapeTier,
|
|
767
|
+
instagramAnalysisTierFrom,
|
|
768
|
+
instagramAnalysisCreditId,
|
|
769
|
+
buildInstagramScrapeCreditId,
|
|
770
|
+
resolveInstagramScrapeCreditId,
|
|
771
|
+
instagramScrapeSources,
|
|
772
|
+
instagramScrapeCreditIdFromNode,
|
|
773
|
+
splitInstagramTargets,
|
|
774
|
+
clampInstagramFeaturedIndex,
|
|
775
|
+
featuredInstagramOutputs,
|
|
776
|
+
type InstagramScrapeMode,
|
|
777
|
+
type InstagramScrapePeriod,
|
|
778
|
+
type InstagramScrapeTier,
|
|
779
|
+
type InstagramFormat,
|
|
780
|
+
type FeaturedInstagramOutputs,
|
|
781
|
+
type InstagramNodeQuoteFields,
|
|
782
|
+
} from "./instagram-scrape.js"
|
|
783
|
+
|
|
625
784
|
export { VARIABLES_HANDLE_ID, buildConditionVariables } from "./condition-variables.js"
|
|
626
785
|
|
|
627
786
|
export { extractAllGeneratedResults, extractGeneratedJsonAsList, spreadJsonArrayIfSingleton } from "./generated-results.js"
|
|
@@ -782,8 +941,27 @@ export {
|
|
|
782
941
|
KINETIC_CAPTION_STYLES,
|
|
783
942
|
ALL_CAPTION_STYLES,
|
|
784
943
|
isKineticCaptionStyle,
|
|
944
|
+
CAPTION_LOOK_IDS,
|
|
945
|
+
CAPTION_LOOKS,
|
|
946
|
+
DEFAULT_CAPTION_LOOK,
|
|
947
|
+
DEFAULT_SUBTITLE_LOOK,
|
|
948
|
+
KINETIC_ONLY_CAPTION_LEVER_KEYS,
|
|
949
|
+
captionRoutesToRemotion,
|
|
950
|
+
CAPTION_MAX_WORDS_PER_LINE_MIN,
|
|
951
|
+
CAPTION_MAX_WORDS_PER_LINE_MAX,
|
|
952
|
+
CAPTION_LEVER_BOUNDS,
|
|
953
|
+
normalizeCaptionNumericLevers,
|
|
954
|
+
autoStrokeWidth,
|
|
955
|
+
resolveCaptionLook,
|
|
956
|
+
resolveCaptionLevers,
|
|
785
957
|
} from "./caption-styles.js"
|
|
786
|
-
export type { StaticCaptionStyle, KineticCaptionStyle, CaptionStyle } from "./caption-styles.js"
|
|
958
|
+
export type { StaticCaptionStyle, KineticCaptionStyle, CaptionStyle, CaptionLookId, CaptionLookLevers, KineticOnlyCaptionLeverKey } from "./caption-styles.js"
|
|
959
|
+
|
|
960
|
+
export {
|
|
961
|
+
transcribeWordTimestampsRefusal,
|
|
962
|
+
findWordlessTranscriptFeeds,
|
|
963
|
+
} from "./transcribe-preflight.js"
|
|
964
|
+
export type { PreflightGraphNode, PreflightGraphEdge, WordlessTranscriptFeed } from "./transcribe-preflight.js"
|
|
787
965
|
|
|
788
966
|
// Sound parameter-node dimensions (music + voice pickers + backend hints)
|
|
789
967
|
|
|
@@ -822,7 +1000,7 @@ export type {
|
|
|
822
1000
|
WorkflowImportSkippedAsset,
|
|
823
1001
|
WorkflowAssetKind,
|
|
824
1002
|
} from "./workflow-export.js"
|
|
825
|
-
export { stripExportContent } from "./workflow-export.js"
|
|
1003
|
+
export { stripExportContent, stripUnownedRefs } from "./workflow-export.js"
|
|
826
1004
|
|
|
827
1005
|
export { validateSubWorkflowRoutes } from "./sub-workflow-validation.js"
|
|
828
1006
|
|
|
@@ -972,6 +1150,22 @@ export {
|
|
|
972
1150
|
|
|
973
1151
|
export { SUNO_TRACK_SOURCE_TYPES } from "./suno-track-sources.js"
|
|
974
1152
|
|
|
1153
|
+
// --- Video URL node + social-video import (host allowlist, node output rule) ---
|
|
1154
|
+
export {
|
|
1155
|
+
SOCIAL_VIDEO_HOSTS,
|
|
1156
|
+
YOUTUBE_HOSTS,
|
|
1157
|
+
INSTAGRAM_HOSTS,
|
|
1158
|
+
VIDEO_LINK_TOLERANT_CONSUMER_TYPES,
|
|
1159
|
+
hostnameMatchesAllowlist,
|
|
1160
|
+
hasUrlParserHazard,
|
|
1161
|
+
isSocialVideoUrl,
|
|
1162
|
+
detectVideoLinkPlatform,
|
|
1163
|
+
videoLinkDownloadedFile,
|
|
1164
|
+
resolveVideoLinkOutput,
|
|
1165
|
+
videoLinkNeedsDownload,
|
|
1166
|
+
} from "./video-link.js"
|
|
1167
|
+
export type { VideoLinkPlatform, VideoLinkNodeFields } from "./video-link.js"
|
|
1168
|
+
|
|
975
1169
|
export {
|
|
976
1170
|
VOICE_CHANGER_MODELS,
|
|
977
1171
|
VOICE_CHANGER_MODEL_IDS,
|
|
@@ -1114,3 +1308,12 @@ export * from "./scene3d-input-assets.js"
|
|
|
1114
1308
|
export * from "./video-output-canvas.js"
|
|
1115
1309
|
export * from "./video-frame-fit.js"
|
|
1116
1310
|
export type { CharacterMotionMetadata } from "./character-motion-metadata.js"
|
|
1311
|
+
|
|
1312
|
+
// --- EDL: the edit decision list contract (podcast editing primitives).
|
|
1313
|
+
// Types + validators + pure remap/duration functions; structural only. ---
|
|
1314
|
+
export * from "./edl.js"
|
|
1315
|
+
export * from "./speaker-layouts.js"
|
|
1316
|
+
export * from "./edl-multicam.js"
|
|
1317
|
+
export * from "./edit-plan-contract.js"
|
|
1318
|
+
|
|
1319
|
+
export { VIDEO_DURATION_AUTO, isAutoVideoDuration } from "./video-duration-auto.js"
|