@hubfluencer/mcp 0.11.0 → 0.13.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/src/core.ts CHANGED
@@ -275,6 +275,8 @@ export interface NormalizedStatus {
275
275
  failure_source?: string;
276
276
  /** Short only: paid generation attempt number that failed. */
277
277
  failure_attempt?: number;
278
+ /** Short only: current paid attempt; echo when cancelling. */
279
+ generation_attempt?: number;
278
280
  /** Editor only: the newest delivered render no longer matches the live project. */
279
281
  stale?: boolean;
280
282
  /** Editor only: current scene ids that are still generating. */
@@ -361,6 +363,8 @@ export function normalizeStatus(
361
363
  status.failure_source = d.failure_source;
362
364
  if (typeof d.failure_attempt === "number")
363
365
  status.failure_attempt = d.failure_attempt;
366
+ if (typeof d.generation_attempt === "number")
367
+ status.generation_attempt = d.generation_attempt;
364
368
  // Additive free-re-render bookkeeping (2026-07 API): surfaced only when
365
369
  // the server actually sends the booleans, so older payloads normalize
366
370
  // byte-identically. A failed free re-render does NOT flip stage to
@@ -464,6 +468,13 @@ export function normalizeStatus(
464
468
  batchStatus === "running" ||
465
469
  batchStatus === "preparing" ||
466
470
  batchStatus === "awaiting_previews";
471
+ // The scene batch commits `completed` before the durable auto-render handoff
472
+ // creates its VideoResult row. While the persisted intent remains armed, the
473
+ // server still owns the project and a reconciler may create the render at any
474
+ // moment. Treat that narrow gap as active work so wait_for_completion cannot
475
+ // return an idle/terminal result just before the render appears.
476
+ const autoRenderHandoffActive =
477
+ batchStatus === "completed" && d.auto_render_after_batch === true;
467
478
  const batchRetryRequired = batchStatus === "paused_for_retry";
468
479
  // A parked batch that ran out of credits: it cannot progress without the user
469
480
  // topping up or reducing scope, so it is a needs-user-action TERMINAL state
@@ -567,6 +578,7 @@ export function normalizeStatus(
567
578
  newerMusicVersions.some(versionActive);
568
579
  const childWorkActive =
569
580
  batchActive ||
581
+ autoRenderHandoffActive ||
570
582
  renderActive ||
571
583
  scenarioActive ||
572
584
  narrationActive ||
@@ -670,6 +682,7 @@ export function normalizeStatus(
670
682
  else if (batchInsufficientCredits) stage = "insufficient_credits";
671
683
  else if (activeSegments.length > 0) stage = "segment_processing";
672
684
  else if (batchActive) stage = "segment_generation";
685
+ else if (autoRenderHandoffActive) stage = "rendering";
673
686
  else if (renderActive) stage = "rendering";
674
687
  else if (scenarioActive) stage = "scenario_processing";
675
688
  else if (narrationActive) stage = "narration_processing";
@@ -705,7 +718,7 @@ export function normalizeStatus(
705
718
  : null) ??
706
719
  actionableChildError ??
707
720
  (batchInsufficientCredits
708
- ? "Batch generation paused: not enough credits to finish. Top up or reduce scope, then resume."
721
+ ? "Batch generation paused: not enough credits to finish. Top up or reduce scope, then invoke the generation/render path again; retry_editor_batch only applies to paused_for_retry."
709
722
  : null)),
710
723
  stale,
711
724
  active_segment_ids: activeSegments
@@ -856,7 +869,6 @@ export interface EditorAdKeyArgs {
856
869
  logo_treatment?: string;
857
870
  logo_position?: string;
858
871
  logo_duration_seconds?: number;
859
- cast_mode?: string;
860
872
  /** Identities of the retained, pre-create asset byte snapshots. */
861
873
  product_image_identity?: string;
862
874
  closing_image_identity?: string;
@@ -896,7 +908,6 @@ export function editorAdCreateKey(a: EditorAdKeyArgs): string {
896
908
  a.logo_duration_seconds === undefined
897
909
  ? ""
898
910
  : String(a.logo_duration_seconds),
899
- a.cast_mode ?? "",
900
911
  );
901
912
  }
902
913
 
@@ -931,7 +942,6 @@ export function editorAdAutopilotKey(slug: string, a: EditorAdKeyArgs): string {
931
942
  a.logo_duration_seconds === undefined
932
943
  ? ""
933
944
  : String(a.logo_duration_seconds),
934
- a.cast_mode ?? "",
935
945
  a.max_credits === undefined ? "" : String(a.max_credits),
936
946
  );
937
947
  }
@@ -1076,10 +1086,9 @@ export function validateLanguage(language: string | undefined): string | null {
1076
1086
  export function validateProductPrompt(
1077
1087
  prompt: string | undefined,
1078
1088
  ): string | null {
1079
- // A trimmed-empty string is a no-op on every path the server exposes:
1080
- // pre-launch override handling drops blank values (leave the stored value
1081
- // untouched) and the editor prompt is valid when blank, so treat "" the same
1082
- // as undefined. Still reject 1–9 non-blank chars (too short to be a brief).
1089
+ // Empty is valid but its meaning is endpoint-specific: draft creation omits
1090
+ // it, while Autopilot treats an explicitly present blank as an atomic clear.
1091
+ // Still reject 1–9 non-blank chars (too short to be a brief).
1083
1092
  if (prompt === undefined) return null;
1084
1093
  const len = prompt.trim().length;
1085
1094
  if (len === 0) return null;