@nodaro/shared 3.8.0 → 3.10.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 (53) hide show
  1. package/dist/index.cjs +325 -63
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +806 -41
  4. package/dist/index.d.ts +806 -41
  5. package/dist/index.js +295 -64
  6. package/dist/index.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/__tests__/credit-identifiers.test.ts +51 -1
  9. package/src/__tests__/gvp-supported-providers.test.ts +20 -3
  10. package/src/__tests__/model-catalog-sections.test.ts +59 -0
  11. package/src/__tests__/model-tree.test.ts +5 -2
  12. package/src/__tests__/parameter-node-value.test.ts +35 -0
  13. package/src/__tests__/pricing-default-duration.test.ts +45 -0
  14. package/src/__tests__/prompt-length-limits.test.ts +4 -0
  15. package/src/__tests__/scene3d-delivery-review.test.ts +512 -0
  16. package/src/__tests__/suno-credit-type.test.ts +46 -0
  17. package/src/__tests__/template-categories.test.ts +45 -0
  18. package/src/__tests__/video-ref-limits.test.ts +11 -2
  19. package/src/credit-identifiers.ts +64 -14
  20. package/src/i18n/camera-motions.ar.ts +5 -5
  21. package/src/i18n/camera-motions.de.ts +5 -5
  22. package/src/i18n/camera-motions.es.ts +5 -5
  23. package/src/i18n/camera-motions.fr.ts +5 -5
  24. package/src/i18n/camera-motions.he.ts +5 -5
  25. package/src/i18n/camera-motions.hi.ts +5 -5
  26. package/src/i18n/camera-motions.ja.ts +5 -5
  27. package/src/i18n/camera-motions.ko.ts +5 -5
  28. package/src/i18n/camera-motions.pt-BR.ts +5 -5
  29. package/src/i18n/camera-motions.ru.ts +5 -5
  30. package/src/i18n/camera-motions.zh-CN.ts +5 -5
  31. package/src/i18n/character-motion.ar.ts +1031 -0
  32. package/src/i18n/character-motion.de.ts +1031 -0
  33. package/src/i18n/character-motion.es.ts +1031 -0
  34. package/src/i18n/character-motion.fr.ts +1031 -0
  35. package/src/i18n/character-motion.he.ts +1031 -0
  36. package/src/i18n/character-motion.hi.ts +1031 -0
  37. package/src/i18n/character-motion.ja.ts +1031 -0
  38. package/src/i18n/character-motion.ko.ts +1031 -0
  39. package/src/i18n/character-motion.pt-BR.ts +1031 -0
  40. package/src/i18n/character-motion.ru.ts +1031 -0
  41. package/src/i18n/character-motion.zh-CN.ts +1031 -0
  42. package/src/i18n/types.ts +1 -0
  43. package/src/index.ts +28 -0
  44. package/src/model-catalog.ts +88 -35
  45. package/src/model-constants.ts +118 -24
  46. package/src/node-execution-state.ts +95 -0
  47. package/src/parameter-node-value.ts +33 -0
  48. package/src/presentation-utils.ts +1 -0
  49. package/src/pro-3d-render.ts +159 -0
  50. package/src/scene3d-delivery-notes.ts +490 -0
  51. package/src/scene3d-v2-plan.ts +8 -2
  52. package/src/smart-cut-windows.ts +15 -10
  53. package/src/template-categories.ts +67 -0
@@ -45,6 +45,7 @@ export const PARAMETER_NODE_TYPES: ReadonlySet<string> = new Set([
45
45
  "post-process-effects",
46
46
  "action-fx",
47
47
  "character-fx",
48
+ "character-motion",
48
49
  "transition",
49
50
  "loop-subject",
50
51
  "scene-count",
@@ -77,6 +78,36 @@ export const HINT_EXEMPT_PARAMETER_TYPES: ReadonlySet<string> = new Set([
77
78
  "aspect-ratio",
78
79
  ])
79
80
 
81
+ /**
82
+ * Parameter pickers whose fragment only makes sense in MOTION — a camera move,
83
+ * a transition, a timeline, a character effect or a character movement. Every
84
+ * still-image consumer (generate-image, edit-image, image-to-image,
85
+ * modify-image, location) excludes these on BOTH executors and in the add-node
86
+ * popup. One set instead of three hand-synced copies: `STILL_IMAGE_EXCLUDE_TYPES`
87
+ * (frontend cinematography-hints.ts and backend payload-builder.ts) and
88
+ * `MOTION_ONLY_PICKER_TYPES` (frontend node-compatibility.ts) alias it.
89
+ */
90
+ export const VIDEO_ONLY_PARAMETER_NODE_TYPES: ReadonlySet<string> = new Set([
91
+ "camera-motion",
92
+ "temporal",
93
+ "transition",
94
+ "character-fx",
95
+ "character-motion",
96
+ ])
97
+
98
+ /**
99
+ * Pickers whose fragment depends on OTHER nodes wired into them — camera
100
+ * motion's start / end states, character motion's target and partner names —
101
+ * so both executors must pass the graph to `getParameterPromptHint` for them.
102
+ * Transition and Character FX compose from the graph in the editor preview but
103
+ * are deliberately NOT here: adding them changes the prompt of workflows that
104
+ * already exist, which is its own reviewed change.
105
+ */
106
+ export const EXECUTION_GRAPH_COMPOSED_PARAMETER_TYPES: ReadonlySet<string> = new Set([
107
+ "camera-motion",
108
+ "character-motion",
109
+ ])
110
+
80
111
  /**
81
112
  * Extra person-dimension data-field names contributed by registered person
82
113
  * packs. Content-free (field-name strings only) — populated at runtime by
@@ -158,6 +189,8 @@ export function getParameterValue(
158
189
  return trim(data.actionFx)
159
190
  case "character-fx":
160
191
  return trim(data.characterFx)
192
+ case "character-motion":
193
+ return trim(data.characterMotion)
161
194
  case "transition":
162
195
  return trim(data.transition)
163
196
  case "style":
@@ -369,6 +369,7 @@ export const INPUT_FIELD_MAP: Record<string, InputFieldSchema> = {
369
369
  "post-process-effects": { key: "postProcess", type: "select" },
370
370
  "action-fx": { key: "actionFx", type: "select" },
371
371
  "character-fx": { key: "characterFx", type: "select" },
372
+ "character-motion": { key: "characterMotion", type: "select" },
372
373
  "transition": { key: "transition", type: "select" },
373
374
  "loop-subject": { key: "loopSubject", type: "select" },
374
375
  // --- Multi-dimension pickers: representative (first) field. Overriding only
@@ -35,6 +35,11 @@ import { z } from "zod"
35
35
  import { SCENE3D_LIMITS, type Scene3DReference } from "./scene3d.js"
36
36
  import { scene3DAnyPlanSchema, type Scene3DPlan } from "./scene3d-v2-plan.js"
37
37
  import { scene3DInputAssetsSchema, type Scene3DInputAsset } from "./scene3d-input-assets.js"
38
+ import {
39
+ SCENE3D_REVIEW_UNAVAILABLE_REASONS,
40
+ type Scene3DRestoredAssertion,
41
+ type Scene3DReviewVerdict,
42
+ } from "./scene3d-delivery-notes.js"
38
43
 
39
44
  /** Canvas/API/MCP node type. */
40
45
  export const PRO3D_RENDER_NODE_TYPE = "pro-3d-render"
@@ -265,6 +270,22 @@ export interface Pro3DRenderCapabilities {
265
270
  // Result
266
271
  // ---------------------------------------------------------------------------
267
272
 
273
+ /**
274
+ * One advisory about a delivered composition.
275
+ *
276
+ * `code` is open-ended — an unknown one is shown, never refused — and it is what tells the two
277
+ * KINDS of advisory apart without knowing anything about the engine that produced them:
278
+ * `SCENE_AUTHORING_ASSUMPTION` (exported as `SCENE3D_AUTHORING_ASSUMPTION_CODE`) is an authoring
279
+ * caveat, "the brief did not say, so the run decided", carrying the planner's own assumption
280
+ * with any normalization the engine applied to it; `SCENE_REVIEW_REFUSED` (exported as
281
+ * `SCENE3D_REVIEW_REFUSED_CODE`) is one objection the paid visual reviewer raised against a
282
+ * scene this job DELIVERED anyway; `SCENE_REVIEW_UNAVAILABLE` (exported as
283
+ * `SCENE3D_REVIEW_UNAVAILABLE_CODE`) says that reviewer gave no usable verdict at all — it was
284
+ * never reached, or answered with nothing usable — so the scene was
285
+ * delivered — or, with the advisory policy off, retained — with no verdict on it, and it LEADS
286
+ * the array because it qualifies every line under it; a `SCENE_QUALITY_*` code is that same
287
+ * reviewer's finding on a job that FAILED, where the finding is the reason there is no video.
288
+ */
268
289
  export interface Pro3DRenderValidationWarning {
269
290
  code: string
270
291
  message: string
@@ -294,6 +315,27 @@ export interface Pro3DRenderResultMetadata {
294
315
  fps: number
295
316
  frames: number
296
317
  duration: number
318
+ /**
319
+ * The planner's own one-or-two-sentence description of what it authored — on a repaired run,
320
+ * of the REPAIR it made, which is the pass that was actually published. Optional and
321
+ * routinely absent: a model that returns no summary is not an error, and a render-only export
322
+ * authored nothing to describe.
323
+ */
324
+ summary?: string
325
+ /**
326
+ * The visual reviewer's verdict, present ONLY on a delivery it did not APPROVE — a scene whose
327
+ * every mandatory assertion passed, published either once the repair budget was spent and the
328
+ * reviewer still objected (`verdict: "refused"`), or with no verdict at all because the review
329
+ * never reached its provider or answered with nothing usable (`verdict: "unavailable"`, with
330
+ * `reason` saying which and `attempts` how many times it was asked). `validation.status` is
331
+ * `"passed"` on both, so this field's presence — not the
332
+ * status, and not the warning count — is what tells them from a clean result.
333
+ *
334
+ * Use {@link scene3DReviewVerdictOf} rather than reading it by hand, and
335
+ * {@link scene3DReviewNote} rather than writing the sentence for it: a banner that says "the
336
+ * reviewer refused this scene" about one NO reviewer saw invents an opinion.
337
+ */
338
+ review?: Scene3DReviewVerdict
297
339
  }
298
340
 
299
341
  /**
@@ -331,6 +373,44 @@ export interface Pro3DRenderJobOutput {
331
373
  }
332
374
  renderer: string
333
375
  metadata: Pro3DRenderResultMetadata
376
+ /**
377
+ * Repair passes actually RUN — never the number of authoring passes, so a composition
378
+ * accepted first time reports `0` rather than `1`. Optional and ABSENT (not `0`) on the
379
+ * render-only lane, which authored nothing and had no repair budget to spend: reporting a
380
+ * count there would be a claim about a run that never happened.
381
+ */
382
+ repairPasses?: number
383
+ /**
384
+ * Pre-build planner retries, counted apart from {@link repairPasses} because they spent a
385
+ * different thing: a recipe the compiler would not ADMIT is re-asked of the planner without
386
+ * a build, so no repair pass went with it. Optional, and absent on a run that needed none.
387
+ */
388
+ admissionRetries?: number
389
+ /**
390
+ * Repairs the engine authored ITSELF, by applying the compiler's own structured remedy instead
391
+ * of asking the planner.
392
+ *
393
+ * Counted APART from {@link repairPasses} and never folded into it, the same way
394
+ * {@link admissionRetries} is: these passes have their own quoted allowance — a `mechanical`
395
+ * line on the quote, released when unspent — rather than spending one of the caller's repairs.
396
+ * The identity the pricing keeps is
397
+ * `buildPasses === authoringPasses + repairPasses + mechanicalPasses`.
398
+ *
399
+ * ONE exception, discriminated by the QUOTE and not by this result: a run quoted before that
400
+ * allowance existed has no `mechanical` quote line, and there the pass charged a repair, making
401
+ * the count a subset of `repairPasses`. Read the quote you were given rather than inferring the
402
+ * accounting from the counts.
403
+ *
404
+ * Optional, and absent both on a run that needed none and on an engine that does not report it.
405
+ */
406
+ mechanicalPasses?: number
407
+ /**
408
+ * Mandatory assertions the engine put BACK after a planner answer re-shaped one the feedback
409
+ * had not named — restored to the last admitted recipe's exact form so the run continues
410
+ * instead of refusing over a value the engine already held. Each is also an
411
+ * `ASSERTION_RESTORED` warning. Optional; absent on a run that restored nothing.
412
+ */
413
+ restoredAssertions?: Scene3DRestoredAssertion[]
334
414
  /** Short, user-safe note about what this revision contains. Never diagnostics. */
335
415
  changeSummary?: string
336
416
  }
@@ -347,6 +427,55 @@ export interface Pro3DRenderJobOutput {
347
427
  * them to satisfy the schema; a runtime that has not produced them yet simply
348
428
  * does not parse as complete, which is the honest answer.
349
429
  */
430
+ /**
431
+ * The visual reviewer's verdict on a delivery it did not approve, read tolerantly.
432
+ *
433
+ * Every member below is permissive on purpose: this schema is OPTIONAL inside a result that is
434
+ * otherwise complete, and a delivered scene with a real MP4 must never fail to parse — and so
435
+ * blank a video the platform already rendered and charged for — over a malformed advisory. An
436
+ * objection that arrives without frames parses with none; an unknown key is kept.
437
+ *
438
+ * That tolerance is exactly what a narrow `verdict` would have thrown away. Declared as
439
+ * `z.literal("refused")` the schema refused the whole result of an UNREVIEWED delivery — a real,
440
+ * paid, playable scene — over a discriminant it had never been taught, which is the one failure
441
+ * mode the rest of this block is written to avoid. `reason` and `attempts` are therefore
442
+ * permissive in the same direction, and with `.catch` rather than `.default`: a value that is
443
+ * absent AND one that is malformed both fall back, because the caller's alternative is losing a
444
+ * delivered MP4 over a count that only ever decides a sentence. `attempts` falls back to `1` —
445
+ * the review was asked at least once, or there would be no verdict to read — and `reason` to
446
+ * `"provider"`, the only cause an older engine emits. The causes it KEEPS are
447
+ * `SCENE3D_REVIEW_UNAVAILABLE_REASONS`, read from the one list `scene3DReviewVerdictOf` and
448
+ * `scene3DReviewNote` also read, never re-spelled here. `verdict` is the one member that stays strict: it is
449
+ * the discriminant, and guessing it is how a scene nobody reviewed gets reported as refused.
450
+ */
451
+ const pro3DRenderReviewFindingsShape = {
452
+ objections: z.array(
453
+ z
454
+ .object({
455
+ category: z.string(),
456
+ what: z.string(),
457
+ correction: z.string().optional(),
458
+ frames: z.array(z.number().int().min(0)).default([]),
459
+ })
460
+ .passthrough(),
461
+ ),
462
+ observed: z.string().optional(),
463
+ }
464
+
465
+ export const pro3DRenderReviewVerdictSchema = z.union([
466
+ z
467
+ .object({ verdict: z.literal("refused"), ...pro3DRenderReviewFindingsShape })
468
+ .passthrough(),
469
+ z
470
+ .object({
471
+ verdict: z.literal("unavailable"),
472
+ reason: z.enum(SCENE3D_REVIEW_UNAVAILABLE_REASONS).catch("provider"),
473
+ attempts: z.number().int().min(1).catch(1),
474
+ ...pro3DRenderReviewFindingsShape,
475
+ })
476
+ .passthrough(),
477
+ ])
478
+
350
479
  export const pro3DRenderShotStillSchema = z
351
480
  .object({
352
481
  shotIndex: z.number().int().min(0),
@@ -387,8 +516,38 @@ export const pro3DRenderJobOutputSchema = z
387
516
  fps: z.number().positive(),
388
517
  frames: z.number().int().positive(),
389
518
  duration: z.number().positive(),
519
+ summary: z.string().optional(),
520
+ /**
521
+ * Degrades to absent rather than refusing the RESULT, which is the whole lesson of the
522
+ * verdict this round added. A narrow `verdict` here did not merely mis-read an unreviewed
523
+ * delivery — it failed `isPro3DRenderJobOutput` for the entire job, blanking a real,
524
+ * paid, playable MP4 over an advisory field. A verdict a future engine invents must cost
525
+ * at most itself; the `SCENE_REVIEW_*` entry in `validation.warnings[]` still arrives
526
+ * either way, because that array has no code enum.
527
+ */
528
+ review: pro3DRenderReviewVerdictSchema.optional().catch(undefined),
390
529
  })
391
530
  .passthrough(),
531
+ repairPasses: z.number().int().min(0).optional(),
532
+ admissionRetries: z.number().int().min(0).optional(),
533
+ mechanicalPasses: z.number().int().min(0).optional(),
534
+ // Tolerant like the review verdict above, and for the same reason: this rides a result that
535
+ // already has a real MP4, so a malformed entry must never blank a video the platform rendered
536
+ // and charged for. The identity fields are required because an entry without them names
537
+ // nothing; `value` is unknown because a restored assertion holds whatever it holds.
538
+ restoredAssertions: z
539
+ .array(
540
+ z
541
+ .object({
542
+ op: z.string(),
543
+ path: z.string(),
544
+ value: z.unknown().optional(),
545
+ assertionId: z.string(),
546
+ reason: z.string(),
547
+ })
548
+ .passthrough(),
549
+ )
550
+ .optional(),
392
551
  changeSummary: z.string().optional(),
393
552
  })
394
553
  .passthrough()