@cueframe/kernel 0.1.3 → 0.1.4

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 (118) hide show
  1. package/dist/_members/authoring/agent/errors.d.ts +8 -0
  2. package/dist/_members/authoring/motion/materializeMotionPresetOps.d.ts +4 -0
  3. package/dist/_members/authoring/types.d.ts +1 -1
  4. package/dist/_members/cloud-import/CloudImportService.d.ts +3 -4
  5. package/dist/_members/cloud-import/ImportProvider.d.ts +3 -7
  6. package/dist/_members/cloud-import/cloudConfig.d.ts +0 -6
  7. package/dist/_members/cloud-import/index.d.ts +2 -4
  8. package/dist/_members/composition/graphics-plan/schemas.d.ts +20 -20
  9. package/dist/_members/composition/primitive-catalog/projection.d.ts +2 -1
  10. package/dist/_members/composition/projection/behind-readiness.d.ts +4 -2
  11. package/dist/_members/composition/validators/brandKit.d.ts +54 -94
  12. package/dist/_members/composition/validators/composePlan.d.ts +52 -52
  13. package/dist/_members/composition/validators/composition.d.ts +213 -253
  14. package/dist/_members/composition/validators/font.d.ts +2 -2
  15. package/dist/_members/composition/validators/index.d.ts +1 -0
  16. package/dist/_members/composition/validators/opaqueId.d.ts +13 -0
  17. package/dist/_members/composition/validators/project.d.ts +11 -15
  18. package/dist/_members/composition/validators/render.d.ts +372 -534
  19. package/dist/_members/composition/validators/session.d.ts +19 -39
  20. package/dist/_members/composition/validators/webhook.d.ts +8 -16
  21. package/dist/_members/composition-ops/index.d.ts +192 -228
  22. package/dist/_members/director/ai-sdk/messages.d.ts +2 -2
  23. package/dist/_members/director/domain/chat.d.ts +4 -4
  24. package/dist/_members/director/testing/contract.d.ts +1 -1
  25. package/dist/_members/errors/registry.d.ts +12 -0
  26. package/dist/_members/mcp/adapter.d.ts +19 -0
  27. package/dist/_members/mcp/curation.d.ts +4 -0
  28. package/dist/_members/mcp/generated/operations.d.ts +2 -2
  29. package/dist/_members/media-model/api.d.ts +53 -109
  30. package/dist/_members/media-model/generation.d.ts +2 -2
  31. package/dist/_members/media-model/index.d.ts +1 -0
  32. package/dist/_members/media-model/opaqueId.d.ts +10 -0
  33. package/dist/_members/render-harness/localRender.d.ts +3 -0
  34. package/dist/_members/render-harness/localRender.d.ts.map +1 -1
  35. package/dist/authoring/build-tools.js +6 -6
  36. package/dist/authoring/context.js +4 -4
  37. package/dist/authoring/tools.js +5 -5
  38. package/dist/authoring.js +39 -22
  39. package/dist/chunk-2SNY75AR.js +498 -0
  40. package/dist/{chunk-ZPRBGW4Y.js → chunk-7TQCR7AB.js} +1 -1
  41. package/dist/{chunk-SDCEJAO2.js → chunk-7V3F5HO4.js} +1 -1
  42. package/dist/{chunk-BZZTVOGG.js → chunk-D2EGO543.js} +5 -5
  43. package/dist/{chunk-TO4BFNLJ.js → chunk-D6S3ZKIY.js} +1 -1
  44. package/dist/{chunk-ICSZF37W.js → chunk-JRIPQ7DN.js} +1 -1
  45. package/dist/{chunk-TFGKUWHY.js → chunk-JTVFIN6H.js} +15 -19
  46. package/dist/{chunk-DCVJWGIA.js → chunk-JY26PIRP.js} +2 -2
  47. package/dist/{chunk-DWLNPNC4.js → chunk-LSP4HN5N.js} +1 -1
  48. package/dist/{chunk-DJW3UGBH.js → chunk-PJ4R4N4Q.js} +83 -9
  49. package/dist/{chunk-TXSFYUZH.js → chunk-QSDFTYKV.js} +1 -1
  50. package/dist/{chunk-AW57IWNW.js → chunk-R5BMJ2NX.js} +20 -1
  51. package/dist/{chunk-DL7WYISQ.js → chunk-RQ2G4DXI.js} +201 -223
  52. package/dist/{chunk-NQSMEUJ6.js → chunk-RXCEPCAQ.js} +102 -41
  53. package/dist/{chunk-TMB5AY6Q.js → chunk-TLVPDT4R.js} +1 -1
  54. package/dist/{chunk-GIA2SVVB.js → chunk-WTT3GGCA.js} +9 -4
  55. package/dist/{chunk-HBVAZXYO.js → chunk-YE3F4LNJ.js} +17 -17
  56. package/dist/{chunk-KFECIHED.js → chunk-YXEZ75MB.js} +5 -5
  57. package/dist/{chunk-TPA6PYN2.js → chunk-ZBRPF6GV.js} +25 -10
  58. package/dist/cloud-import.js +20 -116
  59. package/dist/compose/renderer.js +17 -17
  60. package/dist/compose.js +18 -18
  61. package/dist/composition/graphics-plan.js +1 -1
  62. package/dist/composition/ops.js +3 -3
  63. package/dist/composition/primitive-catalog.js +1 -1
  64. package/dist/composition/projection.js +2 -2
  65. package/dist/composition/validators.js +4 -2
  66. package/dist/composition-ops.js +6 -6
  67. package/dist/composition.js +6 -4
  68. package/dist/{context-JLLU3MYD.js → context-XWNT6QZH.js} +4 -4
  69. package/dist/core/render.js +3 -3
  70. package/dist/core/select.js +2 -2
  71. package/dist/core.js +3 -3
  72. package/dist/director/ai-sdk.js +3 -3
  73. package/dist/director/domain.js +2 -2
  74. package/dist/director.js +3 -3
  75. package/dist/errors.js +1 -1
  76. package/dist/mcp/adapter.js +18 -11
  77. package/dist/mcp/core.js +1 -1
  78. package/dist/mcp/curation.js +5 -1
  79. package/dist/mcp/server.js +4 -4
  80. package/dist/mcp.js +4 -4
  81. package/dist/media-model/media-kind.js +98 -9
  82. package/dist/media-model.js +83 -77
  83. package/dist/nle-export.js +18 -18
  84. package/dist/primitives/backgrounds.js +2 -2
  85. package/dist/primitives/captions.js +3 -3
  86. package/dist/primitives/effects.js +2 -2
  87. package/dist/primitives/hero-text.js +2 -2
  88. package/dist/primitives/layouts.js +2 -2
  89. package/dist/primitives/lib/index.js +12 -12
  90. package/dist/primitives/lib.js +12 -12
  91. package/dist/primitives/scenes.js +2 -2
  92. package/dist/primitives/text.js +2 -2
  93. package/dist/primitives/ui-blocks.js +2 -2
  94. package/dist/primitives.js +19 -19
  95. package/dist/render-harness.js +4 -2
  96. package/package.json +9 -34
  97. package/dist/_members/authoring/prompts/designReviewerPrompt.d.ts +0 -2
  98. package/dist/_members/cloud-import/MediaItemPreprocessor.d.ts +0 -18
  99. package/dist/_members/cloud-import/multipartUpload.d.ts +0 -12
  100. package/dist/_members/convex-api/api.d.ts +0 -5
  101. package/dist/_members/convex-api/api.generated.d.ts +0 -1444
  102. package/dist/_members/convex-api/dataModel.d.ts +0 -6
  103. package/dist/chunk-6IU2UQI5.js +0 -107
  104. package/dist/chunk-EP2Y6M2J.js +0 -64
  105. package/dist/chunk-WZH57M53.js +0 -494
  106. package/dist/cloud-import/multipart.d.ts +0 -1
  107. package/dist/cloud-import/multipart.js +0 -8
  108. package/dist/convex-api/dataModel.d.ts +0 -1
  109. package/dist/convex-api/dataModel.js +0 -0
  110. package/dist/convex-api.d.ts +0 -1
  111. package/dist/convex-api.js +0 -8
  112. package/dist/{chunk-RP4SXXLJ.js → chunk-3PM6VICZ.js} +3 -3
  113. package/dist/{chunk-UQSOS726.js → chunk-6ABIXGLO.js} +4 -4
  114. package/dist/{chunk-SAMQUUO5.js → chunk-BIBYZJL3.js} +3 -3
  115. package/dist/{chunk-GMD33ZD7.js → chunk-O7GNE4BQ.js} +3 -3
  116. package/dist/{chunk-BKHGL4MB.js → chunk-THJAY7QS.js} +4 -4
  117. package/dist/{chunk-DYZE7JZA.js → chunk-TMIBBD5E.js} +3 -3
  118. package/dist/{chunk-G5BFI32U.js → chunk-XATRRDVG.js} +3 -3
@@ -4,16 +4,16 @@ import {
4
4
  import {
5
5
  getPrimitiveSubtextParam,
6
6
  getPrimitiveTextParam
7
- } from "./chunk-DCVJWGIA.js";
7
+ } from "./chunk-JY26PIRP.js";
8
8
  import {
9
9
  selectAllOverlays
10
- } from "./chunk-ICSZF37W.js";
10
+ } from "./chunk-JRIPQ7DN.js";
11
11
  import {
12
12
  ComposePlan
13
- } from "./chunk-TFGKUWHY.js";
13
+ } from "./chunk-JTVFIN6H.js";
14
14
  import {
15
15
  OverlayClipSource
16
- } from "./chunk-WZH57M53.js";
16
+ } from "./chunk-2SNY75AR.js";
17
17
 
18
18
  // ../authoring/src/tools/toolSets.ts
19
19
  var COMPOSE_PLANNER_TOOLS = [
@@ -63,7 +63,7 @@ var COMPOSE_ROLE_TOOLS = Object.freeze({
63
63
  schema: z.object({}),
64
64
  metadata: { label: "Get Context" },
65
65
  handler: async (_args, capabilities) => {
66
- const { buildDirectorContext } = await import("./context-JLLU3MYD.js");
66
+ const { buildDirectorContext } = await import("./context-XWNT6QZH.js");
67
67
  return buildDirectorContext(capabilities);
68
68
  }
69
69
  },
@@ -9,7 +9,7 @@ import {
9
9
  import {
10
10
  decodeError,
11
11
  scrubSensitive
12
- } from "./chunk-AW57IWNW.js";
12
+ } from "./chunk-R5BMJ2NX.js";
13
13
 
14
14
  // ../director/src/domain/chat.ts
15
15
  import { z } from "zod";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-KYRDKK2D.js";
4
4
  import {
5
5
  Composition
6
- } from "./chunk-WZH57M53.js";
6
+ } from "./chunk-2SNY75AR.js";
7
7
 
8
8
  // ../composition/src/ops/compositionOps.shared.ts
9
9
  function findOrCreateTrackByKind(composition, kind) {
@@ -2,8 +2,9 @@ import {
2
2
  Composition,
3
3
  Copy,
4
4
  Format,
5
- GraphicRole
6
- } from "./chunk-WZH57M53.js";
5
+ GraphicRole,
6
+ OpaqueId
7
+ } from "./chunk-2SNY75AR.js";
7
8
 
8
9
  // ../composition/src/validators/composePlan.ts
9
10
  import { z } from "zod";
@@ -77,7 +78,6 @@ var ComposePlan = z.object({
77
78
 
78
79
  // ../composition/src/validators/brandKit.ts
79
80
  import { z as z2 } from "zod";
80
- import { zid } from "convex-helpers/server/zod3";
81
81
  var EasingValue = z2.union([
82
82
  z2.enum(["linear", "ease", "ease-in", "ease-out", "ease-in-out"]),
83
83
  z2.object({
@@ -101,7 +101,7 @@ var FontRef = z2.union([
101
101
  }),
102
102
  z2.object({
103
103
  kind: z2.literal("uploaded"),
104
- fontId: zid("fonts"),
104
+ fontId: OpaqueId,
105
105
  family: z2.string().optional()
106
106
  })
107
107
  ]);
@@ -331,7 +331,6 @@ var Font = z3.object({
331
331
 
332
332
  // ../composition/src/validators/render.ts
333
333
  import { z as z4 } from "zod";
334
- import { zid as zid2 } from "convex-helpers/server/zod3";
335
334
  var RenderPriority = z4.enum(["interactive", "standard", "background"]);
336
335
  var RenderIntent = z4.enum(["preview", "final"]);
337
336
  var RenderMode = z4.enum(["offline", "live"]);
@@ -362,7 +361,7 @@ var RegistryPin = z4.object({
362
361
  version: z4.string().min(1)
363
362
  });
364
363
  var MediaSourceSnapshot = z4.object({
365
- mediaId: zid2("mediaItems"),
364
+ mediaId: OpaqueId,
366
365
  presignedUrl: z4.string().url(),
367
366
  expiresAt: z4.number().optional()
368
367
  });
@@ -425,9 +424,9 @@ var DestinationResult = z4.object({
425
424
  error: z4.string().optional()
426
425
  });
427
426
  var RenderJob = z4.object({
428
- id: zid2("renderJobs"),
429
- projectId: zid2("projects").optional(),
430
- compositionId: zid2("compositions"),
427
+ id: OpaqueId,
428
+ projectId: OpaqueId.optional(),
429
+ compositionId: OpaqueId,
431
430
  compositionVersionId: z4.string().min(1),
432
431
  status: RenderStatus,
433
432
  progress: RenderProgressPhase.optional(),
@@ -452,7 +451,7 @@ var RenderJob = z4.object({
452
451
  updatedAt: z4.number()
453
452
  });
454
453
  var RenderProgress = z4.object({
455
- jobId: zid2("renderJobs"),
454
+ jobId: OpaqueId,
456
455
  status: RenderStatus,
457
456
  percent: z4.number().min(0).max(100).optional(),
458
457
  framesRendered: z4.number().int().nonnegative().optional(),
@@ -504,13 +503,12 @@ var PrimitiveRegistryEntry = z5.object({
504
503
 
505
504
  // ../composition/src/validators/project.ts
506
505
  import { z as z6 } from "zod";
507
- import { zid as zid3 } from "convex-helpers/server/zod3";
508
506
  var Project = z6.object({
509
- id: zid3("projects"),
507
+ id: OpaqueId,
510
508
  name: z6.string().min(1),
511
509
  defaultFormat: Format.optional(),
512
510
  palConformDefault: z6.union([z6.literal(24), z6.literal(30)]).optional(),
513
- activeCompositionId: zid3("compositions").nullable().optional(),
511
+ activeCompositionId: OpaqueId.nullable().optional(),
514
512
  brandKitId: z6.string().optional(),
515
513
  ownerOrgId: z6.string().optional(),
516
514
  createdAt: z6.number(),
@@ -519,7 +517,6 @@ var Project = z6.object({
519
517
 
520
518
  // ../composition/src/validators/session.ts
521
519
  import { z as z7 } from "zod";
522
- import { zid as zid4 } from "convex-helpers/server/zod3";
523
520
  var SessionMediaRole = z7.enum([
524
521
  "main",
525
522
  "wide",
@@ -528,7 +525,7 @@ var SessionMediaRole = z7.enum([
528
525
  "audio"
529
526
  ]);
530
527
  var SessionMember = z7.object({
531
- mediaId: zid4("mediaItems"),
528
+ mediaId: OpaqueId,
532
529
  role: SessionMediaRole,
533
530
  label: z7.string().optional()
534
531
  // human-readable annotation, e.g., "host's camera"
@@ -538,7 +535,7 @@ var SessionMux = z7.object({
538
535
  audioRole: z7.literal("audio")
539
536
  });
540
537
  var Session = z7.object({
541
- id: zid4("sessions"),
538
+ id: OpaqueId,
542
539
  name: z7.string().min(1),
543
540
  members: z7.array(SessionMember).nonempty(),
544
541
  mux: z7.array(SessionMux).optional(),
@@ -549,7 +546,6 @@ var Session = z7.object({
549
546
 
550
547
  // ../composition/src/validators/webhook.ts
551
548
  import { z as z8 } from "zod";
552
- import { zid as zid5 } from "convex-helpers/server/zod3";
553
549
  var SubstrateWebhookEvent = z8.enum([
554
550
  "render.completed",
555
551
  "media.transcribed",
@@ -565,7 +561,7 @@ var WebhookDeliveryStatus = z8.enum([
565
561
  // retry budget burned through
566
562
  ]);
567
563
  var Webhook = z8.object({
568
- id: zid5("webhooks"),
564
+ id: OpaqueId,
569
565
  url: z8.string().url(),
570
566
  events: z8.array(z8.string().min(1)).nonempty(),
571
567
  signingKeyId: z8.string().optional(),
@@ -577,7 +573,7 @@ var Webhook = z8.object({
577
573
  });
578
574
  var WebhookDelivery = z8.object({
579
575
  id: z8.string().min(1),
580
- webhookId: zid5("webhooks"),
576
+ webhookId: OpaqueId,
581
577
  event: z8.string().min(1),
582
578
  payload: z8.record(z8.string(), z8.unknown()),
583
579
  status: WebhookDeliveryStatus,
@@ -15221,8 +15221,8 @@ function resolution(h) {
15221
15221
  }
15222
15222
  function sceneFps(fps) {
15223
15223
  if (fps === void 0) return void 0;
15224
- if (fps === 24 || fps === 30 || fps === 60) return fps;
15225
- throw new Error(`sceneFormat: unsupported scene fps ${fps} (expected 24|30|60)`);
15224
+ if (fps === 24 || fps === 25 || fps === 30 || fps === 60) return fps;
15225
+ throw new Error(`sceneFormat: unsupported scene fps ${fps} (expected 24|25|30|60)`);
15226
15226
  }
15227
15227
  function sceneFormat(m) {
15228
15228
  if (m.kind !== "scene") return void 0;
@@ -2,7 +2,7 @@ import {
2
2
  selectAllClips,
3
3
  selectAllOverlays,
4
4
  selectSceneMarkers
5
- } from "./chunk-ICSZF37W.js";
5
+ } from "./chunk-JRIPQ7DN.js";
6
6
 
7
7
  // ../authoring/src/context/transcript.ts
8
8
  var MAX_TRANSCRIPT_CHARS = 6e4;
@@ -209,7 +209,10 @@ function formatComposition(json) {
209
209
  ];
210
210
  if (json?.captions) {
211
211
  const segs = json.captions.segments?.length ?? 0;
212
- const words = json.captions.words?.length ?? 0;
212
+ const words = Array.isArray(json.captions.segments) ? json.captions.segments.reduce(
213
+ (total, segment) => total + (Array.isArray(segment?.words) ? segment.words.length : 0),
214
+ 0
215
+ ) : 0;
213
216
  lines.push(`captions: ${segs} segment(s), ${words} word(s) [text elided]`);
214
217
  }
215
218
  if (Array.isArray(json?.markers) && json.markers.length) {
@@ -228,16 +231,71 @@ function formatWarnings(json) {
228
231
 
229
232
  \u26A0 ${warns.join("\n\u26A0 ")}` : "";
230
233
  }
234
+ var CONTEXT_WINDOW_CAP = 6;
235
+ var CONTEXT_FACE_CAP = 3;
236
+ var CONTEXT_SAMPLE_WORDS = 24;
237
+ function formatMediaContext(json) {
238
+ const lines = [];
239
+ const dims = json?.width && json?.height ? `${json.width}\xD7${json.height}` : "unknown dimensions";
240
+ const duration = typeof json?.durationSec === "number" ? fmtClock(json.durationSec) : "unknown duration";
241
+ lines.push(`Media ${json?.mediaId ?? "?"} \u2014 ${dims}, ${duration}`);
242
+ if (json?.thumbnail?.url) lines.push(`thumbnail: ${json.thumbnail.url}`);
243
+ const windows = Array.isArray(json?.faces?.windows) ? json.faces.windows : [];
244
+ lines.push(`faces: ${json?.faces?.status ?? "unknown"} (${windows.length} source window(s))`);
245
+ for (const window of windows.slice(0, CONTEXT_WINDOW_CAP)) {
246
+ const faces = Array.isArray(window?.faces) ? window.faces : [];
247
+ const roster = faces.slice(0, CONTEXT_FACE_CAP).map((face) => {
248
+ const bbox = face?.bbox ?? {};
249
+ const box = [bbox.x, bbox.y, bbox.width, bbox.height].every((value) => typeof value === "number") ? ` bbox:${[bbox.x, bbox.y, bbox.width, bbox.height].map((n) => n.toFixed(3)).join(",")}` : "";
250
+ const speaking = typeof face?.speakingShare === "number" ? ` speaking:${Math.round(face.speakingShare * 100)}%` : "";
251
+ return `${face?.faceId ?? "?"}${box}${speaking}`;
252
+ });
253
+ lines.push(`- ${window?.window?.startSec ?? "?"}\u2192${window?.window?.endSec ?? "?"}s: ${roster.join(" | ") || "no usable subjects"}`);
254
+ }
255
+ if (windows.length > CONTEXT_WINDOW_CAP) lines.push(`- \u2026 ${windows.length - CONTEXT_WINDOW_CAP} more face windows elided`);
256
+ const transcript = json?.transcript;
257
+ const utterances = Array.isArray(transcript?.data?.utterances) ? transcript.data.utterances : Array.isArray(transcript?.data?.data) ? transcript.data.data : [];
258
+ const words = utterances.flatMap((utterance) => Array.isArray(utterance?.words) ? utterance.words : []);
259
+ const sample = words.slice(0, CONTEXT_SAMPLE_WORDS).map((word) => {
260
+ const start = typeof word?.start === "number" ? `@${word.start.toFixed(2)}s` : "";
261
+ return `${word?.word ?? word?.text ?? ""}${start}`;
262
+ }).filter(Boolean);
263
+ lines.push(`transcript: ${transcript?.status ?? "unknown"} (${utterances.length} utterance(s), ${words.length} word(s))`);
264
+ if (sample.length) lines.push(`sample: ${sample.join(" ")}`);
265
+ if (transcript?.status === "ready") {
266
+ lines.push("Use get_transcript(mediaItemId, limit, after/before) for exact paginated word timings.");
267
+ }
268
+ if (json?.beatGrid) {
269
+ const beats = Array.isArray(json.beatGrid.beatTimesMs) ? json.beatGrid.beatTimesMs : [];
270
+ lines.push(`beatGrid: ${json.beatGrid.bpm ?? "?"} bpm, ${beats.length} beats, ${json.beatGrid.method ?? "?"}${beats.length ? `; first ms: ${beats.slice(0, 12).join(",")}` : ""}`);
271
+ } else lines.push("beatGrid: none");
272
+ const wordTimes = Array.isArray(json?.wordGrid?.wordTimesMs) ? json.wordGrid.wordTimesMs : [];
273
+ lines.push(`wordGrid: ${wordTimes.length} onsets${wordTimes.length ? `; first ms: ${wordTimes.slice(0, 12).join(",")}` : ""}`);
274
+ lines.push(`audio: role=${json?.audioRole ?? "none"} envelope=${json?.envelope?.envelopeClass ?? "none"}`);
275
+ const facts = Array.isArray(json?.facts) ? json.facts : [];
276
+ const offers = Array.isArray(json?.offers) ? json.offers : [];
277
+ lines.push(`facts: ${facts.map((fact) => `${fact?.kind ?? "?"}:${fact?.status ?? "?"}`).join(", ") || "none"}`);
278
+ lines.push(`offers: ${offers.map((offer) => `${offer?.kind ?? "?"}${offer?.quotedUsd != null ? `($${offer.quotedUsd})` : ""}`).join(", ") || "none"}`);
279
+ return lines.join("\n");
280
+ }
281
+ function formatTranscriptPage(json) {
282
+ const utterances = Array.isArray(json?.data) ? json.data : Array.isArray(json?.utterances) ? json.utterances : [];
283
+ return JSON.stringify({
284
+ mediaItemId: json?.mediaItemId,
285
+ language: json?.language,
286
+ utterances,
287
+ ...json?.pagination ? { pagination: json.pagination } : {}
288
+ }, null, 2);
289
+ }
231
290
  var CURATED_TOOLS = [
232
291
  {
233
292
  name: "compose",
234
293
  operationId: "compose",
235
294
  pathArgs: { projectId: "id" },
236
- description: 'Start the async Director compose workflow: it authors an ensemble of full composition candidates, verifies each, and saves the winner to the project. Body must set EXACTLY ONE source (mutually exclusive): `briefId` \u2014 author FROM a persisted Brief (the PLANNED path: create_brief first; every Brief field is honored or the compose is refused loudly naming the field); `fromComposition: true` \u2014 author from the project\'s CURRENT composition (the GENERAL path: seed it with apply_composition first \u2014 your media clips are the intent, and any graphics you authored are CARRIED VERBATIM as locked clips the Director authors around, never re-authors or drops); or `suggestionId` \u2014 author from an AI clip suggestion (the CLIPPING path, paired with suggest_briefs). Returns { composeJobId, workflowId, status, streamUrl }. Then call wait_job(kind="compose", id=composeJobId, projectId=...) to block until the winner is selected.',
237
- okFormat: (j, a) => `Compose workflow started.
295
+ description: 'Start an async Director compose job: it authors an ensemble of full composition candidates, verifies each, and saves the winner to the project. Body must set EXACTLY ONE source (mutually exclusive): `briefId` \u2014 author FROM a persisted Brief (the PLANNED path: create_brief first; every Brief field is honored or the compose is refused loudly naming the field); `fromComposition: true` \u2014 author from the project\'s CURRENT composition (the GENERAL path: seed it with apply_composition first \u2014 your media clips are the intent, and any graphics you authored are CARRIED VERBATIM as locked clips the Director authors around, never re-authors or drops); or `suggestionId` \u2014 author from an AI clip suggestion (the CLIPPING path, paired with suggest_briefs). Returns { composeJobId, status, streamUrl }. Then call wait_job(kind="compose", id=composeJobId, projectId=...) to block until the winner is selected.',
296
+ okFormat: (j, a) => `Compose job started.
238
297
 
239
298
  composeJobId: ${j.composeJobId}
240
- workflowId: ${j.workflowId}
241
299
  status: ${j.status}${j.streamUrl ? `
242
300
  streamUrl: ${j.streamUrl}` : ""}
243
301
 
@@ -451,7 +509,21 @@ ${j.tsxSource}`,
451
509
  name: "get_media_context",
452
510
  operationId: "getMediaContext",
453
511
  pathArgs: { mediaItemId: "id" },
454
- description: "Fetch the authoring context for a media item: detected faces (subject boxes per frame) and the transcript. Use this before composing/applying so your crop intents, captions, and timing line up with what is actually in the footage.",
512
+ description: "Fetch bounded authoring context for a media item: dimensions/thumbnail, compact face roster, transcript counts/sample, temporal grids, and fact readiness. The full transcript body is deliberately elided so this read cannot overflow MCP; follow with get_transcript for exact paginated word timings.",
513
+ okFormat: (j) => formatMediaContext(j),
514
+ annotations: { readOnlyHint: true }
515
+ },
516
+ {
517
+ name: "get_transcript",
518
+ operationId: "getMediaTranscript",
519
+ pathArgs: { mediaItemId: "id" },
520
+ queryArgs: {
521
+ after: "Zero-based utterance cursor returned as pagination.nextCursor.",
522
+ before: "Zero-based utterance cursor for a backward page; do not combine with after.",
523
+ limit: "Utterances per page (1\u2013100). Use 20 by default."
524
+ },
525
+ description: "Read exact source-time transcript words in bounded utterance pages. Word start/end values are seconds from the source media start. Pass limit (20 recommended), then pagination.nextCursor as after; the formatter omits the unbounded fullText duplicate.",
526
+ okFormat: (j) => formatTranscriptPage(j),
455
527
  annotations: { readOnlyHint: true }
456
528
  },
457
529
  {
@@ -556,12 +628,12 @@ Render it with create_render(projectId="${a.projectId}", body={ compositionId: "
556
628
  {
557
629
  name: "generate_media",
558
630
  operationId: "generateMedia",
559
- description: 'Generate one first-class Library media item from a prompt. Choose generator: text-to-video | text-to-image | image-to-video | text-to-music | text-to-speech | text-to-sfx | auto. Put aspect/duration/voice/model controls in body.style and first/last/image references in body.refs. Returns { id, status:"generating", workflowId?, estimateUsd? }; returns 402 if the estimate exceeds the per-call ceiling. Async \u2014 call wait_job(kind="media", id=mediaItemId) or use a webhook (media.completed \u2014 status rides the payload). Use the returned id like any other media item.'
631
+ description: 'Generate one first-class Library media item from a prompt. Choose generator: text-to-video | text-to-image | image-to-video | text-to-music | text-to-speech | text-to-sfx | auto. Put supported presentation controls in body.style and first/last/image references in body.refs. Returns { id, status:"generating", estimateUsd? }; returns 402 if the estimate exceeds the per-call ceiling. Async \u2014 call wait_job(kind="media", id=mediaItemId) or use a webhook (media.completed \u2014 status rides the payload). Use the returned id like any other media item.'
560
632
  },
561
633
  {
562
634
  name: "create_upload",
563
635
  operationId: "createMediaUpload",
564
- description: "Ingest a LOCAL file \u2014 bytes you hold, when there is no public URL to hand import_media (prefer import_media whenever the bytes already sit at an https URL). TWO steps: (1) this tool reserves a media row and returns { id, uploadUrl, expiresAt } \u2014 a short-lived presigned PUT URL. PUT the raw file bytes straight to uploadUrl over HTTPS with your declared Content-Type (the bytes go direct to R2, never through MCP; \u2264 ~5 GB per PUT). (2) call finalize_upload({ mediaItemId: id }) to start processing. Body: filename, contentType (allowed enum), size (bytes). Thereafter it is async exactly like import_media: poll list_media for processingStatus, or register a webhook (create_webhook on media.completed). Use the returned id with get_media_context, suggest_briefs, or as a composition source."
636
+ description: "Ingest a LOCAL file \u2014 bytes you hold, when there is no public URL to hand import_media (prefer import_media whenever the bytes already sit at an https URL). TWO steps: (1) this tool reserves a media item and returns { id, uploadUrl, expiresAt } \u2014 a short-lived PUT URL. PUT the raw file bytes to uploadUrl over HTTPS with your declared Content-Type (\u2264 ~5 GB per PUT). (2) call finalize_upload({ mediaItemId: id }) to start processing. Body: filename, contentType (allowed enum), size (bytes). Thereafter it is async exactly like import_media: poll list_media for processingStatus, or register a webhook (create_webhook on media.completed). Use the returned id with get_media_context, suggest_briefs, or as a composition source."
565
637
  },
566
638
  {
567
639
  name: "finalize_upload",
@@ -572,7 +644,7 @@ Render it with create_render(projectId="${a.projectId}", body={ compositionId: "
572
644
  {
573
645
  name: "search_resources",
574
646
  operationId: "searchResources",
575
- description: "Search licensed STOCK media to compose with \u2014 video/photo (Pexels + Pixabay fallback), sfx (Freesound, CC0-only), gif (Klipy). Pass query for ONE search, or queries[] (\u226410) to run them all in a SINGLE call \u2014 strongly prefer the batch when you know several things you need (a 64-search session spent 5m10s on serial round-trips). A batch returns results[], one per query in order, each with its own candidates; a query that fails carries an error and never discards the others. Optional kind [default video], provider pin, limit \u226450 apply to every query in the batch. Returns ranked candidates, each with an opaque candidateId + attribution (author, assetUrl) + license, and a preview URL in the text. FREE + rate-limited + 7-day cached \u2014 reach for this before generate_media when real footage beats synthesis. TO SEE the candidates rather than read about them, pass limit \u22652: thumbnails/audio are attached only when you asked for options to compare, because a preview of a single forced choice is pure cost. Import a chosen candidate into a project with import_resource. Candidates expire after 7 days (re-search to refresh a candidateId).",
647
+ description: "Search licensed stock media to compose with across video, photo, sound effects, and GIFs. Pass query for ONE search, or queries[] (\u226410) to run them all in a SINGLE call \u2014 strongly prefer the batch when you know several things you need. A batch returns results[], one per query in order, each with its own candidates; a query that fails carries an error and never discards the others. Optional kind [default video], provider pin, and limit \u226450 apply to every query in the batch. Returns ranked candidates, each with an opaque candidateId + attribution (author, assetUrl) + license, and a preview URL in the text. FREE + rate-limited + cached \u2014 reach for this before generate_media when real footage beats synthesis. TO SEE the candidates rather than read about them, pass limit \u22652: thumbnails/audio are attached only when you asked for options to compare. Import a chosen candidate into a project with import_resource. Candidate handles expire; re-search to refresh one.",
576
648
  okFormat: (j) => formatResourceCandidates(j),
577
649
  preview: {
578
650
  urls: (j) => (Array.isArray(j?.results) ? j.results.flatMap((r) => Array.isArray(r?.candidates) ? r.candidates : []) : Array.isArray(j?.candidates) ? j.candidates : []).map((c) => c?.previewUrl),
@@ -598,7 +670,7 @@ Render it with create_render(projectId="${a.projectId}", body={ compositionId: "
598
670
  name: "suggest_briefs",
599
671
  operationId: "suggestBriefs",
600
672
  pathArgs: { mediaItemId: "id" },
601
- description: `Run AI clip-suggestion analysis on a long-form media item \u2014 the CLIPPING path (find the best short-form moments). Returns { workflowId, status }; then wait_job(kind="suggestions", id=mediaItemId) \u2014 its terminal lists each suggestion WITH its briefId. When the media belongs to a PROJECT, each finalized suggestion is promoted to a kind-'clip' BRIEF (its window pinned as a beat) \u2014 list_briefs {kind:"clip"} shows them and compose({ briefId }) runs the flagship path from one. Project-less media: pass the suggestion id to compose({ suggestionId }) directly. Clipping is a vertical, NOT the general path.`
673
+ description: `Run AI clip-suggestion analysis on a long-form media item \u2014 the CLIPPING path (find the best short-form moments). Returns { status, alreadyRunning? }; then wait_job(kind="suggestions", id=mediaItemId) \u2014 its terminal lists each suggestion WITH its briefId. When the media belongs to a PROJECT, each finalized suggestion is promoted to a kind-'clip' BRIEF (its window pinned as a beat) \u2014 list_briefs {kind:"clip"} shows them and compose({ briefId }) runs the flagship path from one. Project-less media: pass the suggestion id to compose({ suggestionId }) directly. Clipping is a vertical, NOT the general path.`
602
674
  },
603
675
  {
604
676
  name: "create_webhook",
@@ -916,6 +988,8 @@ export {
916
988
  formatResourceCandidates,
917
989
  formatComposition,
918
990
  formatWarnings,
991
+ formatMediaContext,
992
+ formatTranscriptPage,
919
993
  CURATED_TOOLS,
920
994
  INTERNAL_EDITOR_TOOLS,
921
995
  KNOWN_BACKEND_GAPS,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolveBookendTimeline
3
- } from "./chunk-NQSMEUJ6.js";
3
+ } from "./chunk-RXCEPCAQ.js";
4
4
 
5
5
  // ../execution/compose/src/tokenResolver.ts
6
6
  var DEFAULTS = {
@@ -103,6 +103,8 @@ var ERROR_CODES = {
103
103
  render_not_complete: { stage: "render", category: "authoring", retryable: false, httpStatus: 422 },
104
104
  lambda_infra_failed: { stage: "render", category: "transient", retryable: true, httpStatus: 503 },
105
105
  render_provider_unreachable: { stage: "render", category: "transient", retryable: true, httpStatus: 503 },
106
+ render_provider_start_failed: { stage: "render", category: "transient", retryable: true, httpStatus: 503 },
107
+ behind_split_unsupported: { stage: "validate", category: "authoring", retryable: false, httpStatus: 422 },
106
108
  render_pipeline_unavailable: { stage: "render", category: "transient", retryable: true, httpStatus: 503 },
107
109
  render_route_missing: { stage: "render", category: "internal", retryable: true, httpStatus: 503 },
108
110
  render_pipeline_failed: { stage: "render", category: "transient", retryable: true, httpStatus: 503 },
@@ -208,7 +210,24 @@ var FIX_ALLOW = [
208
210
  "typeMismatches",
209
211
  "constraintViolations"
210
212
  ];
211
- var LOCATOR_ALLOW = ["projectId", "renderId", "requestId", "clipId", "trackId", "compositionPath"];
213
+ var LOCATOR_ALLOW = [
214
+ "projectId",
215
+ "compositionId",
216
+ "renderId",
217
+ "jobId",
218
+ "requestId",
219
+ "workflowId",
220
+ "activityId",
221
+ "stage",
222
+ "clipId",
223
+ "trackId",
224
+ "mediaId",
225
+ "componentId",
226
+ "outputFrame",
227
+ "timecodeMs",
228
+ "providerRequestId",
229
+ "compositionPath"
230
+ ];
212
231
  var GENERIC = {
213
232
  transient: "A temporary error occurred; retry.",
214
233
  internal: "An unexpected error occurred."