@cueframe/kernel 0.1.2 → 0.1.3

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 (46) hide show
  1. package/dist/_members/authoring/index.d.ts +1 -1
  2. package/dist/_members/authoring/prompts/index.d.ts +0 -1
  3. package/dist/_members/convex-api/api.d.ts +3 -0
  4. package/dist/_members/convex-api/api.generated.d.ts +1444 -0
  5. package/dist/_members/convex-api/dataModel.d.ts +3 -1
  6. package/dist/_members/errors/registry.d.ts +103 -1
  7. package/dist/_members/mcp/core.d.ts +1 -1
  8. package/dist/_members/mcp/generated/harness.d.ts +1 -1
  9. package/dist/_members/mcp/generated/operations.d.ts +12 -0
  10. package/dist/_members/mcp/wait.d.ts +1 -1
  11. package/dist/_members/render-harness/remotion-runtime.d.ts +53 -0
  12. package/dist/authoring/prompts.js +1 -5
  13. package/dist/authoring.js +3 -7
  14. package/dist/{chunk-LLUW26BS.js → chunk-AW57IWNW.js} +18 -1
  15. package/dist/{chunk-AO744WIK.js → chunk-DJW3UGBH.js} +41 -30
  16. package/dist/{chunk-W3SIWT7J.js → chunk-DL7WYISQ.js} +267 -13
  17. package/dist/{chunk-PIURX6IZ.js → chunk-GIA2SVVB.js} +1 -1
  18. package/dist/{chunk-CAJQ7H5A.js → chunk-HBVAZXYO.js} +1 -1
  19. package/dist/{chunk-K2IUBCND.js → chunk-HFC3MKXA.js} +0 -51
  20. package/dist/{chunk-TD347SSX.js → chunk-KFECIHED.js} +29 -18
  21. package/dist/{chunk-VHF66LCQ.js → chunk-NQSMEUJ6.js} +2 -2
  22. package/dist/{chunk-QETYXKQQ.js → chunk-SDCEJAO2.js} +97 -14
  23. package/dist/{chunk-LJ5W4ZBU.js → chunk-TMB5AY6Q.js} +1 -1
  24. package/dist/{chunk-ZPLJ24OV.js → chunk-TO4BFNLJ.js} +1 -1
  25. package/dist/{chunk-VFMW3JUY.js → chunk-TXSFYUZH.js} +1 -1
  26. package/dist/{chunk-XQ72DZKJ.js → chunk-ZPRBGW4Y.js} +1 -1
  27. package/dist/compose/renderer.js +2 -2
  28. package/dist/compose.js +5 -5
  29. package/dist/composition/projection.js +2 -2
  30. package/dist/composition-ops.js +3 -3
  31. package/dist/composition.js +2 -2
  32. package/dist/core/render.js +3 -3
  33. package/dist/core/select.js +2 -2
  34. package/dist/core.js +3 -3
  35. package/dist/director/ai-sdk.js +3 -3
  36. package/dist/director/domain.js +2 -2
  37. package/dist/director.js +3 -3
  38. package/dist/errors.js +1 -1
  39. package/dist/mcp/adapter.js +44 -14
  40. package/dist/mcp/core.js +1 -1
  41. package/dist/mcp/curation.js +1 -1
  42. package/dist/mcp/server.js +4 -4
  43. package/dist/mcp.js +4 -4
  44. package/dist/media-model/testing.js +6 -6
  45. package/dist/nle-export.js +5 -5
  46. package/package.json +14 -13
@@ -127,55 +127,6 @@ Call submit_plan with type "plan" if:
127
127
  - Prefer moments where the speaker introduces a concept or transitions topics
128
128
  - At most 1 intro and 1 outro`;
129
129
 
130
- // ../authoring/src/prompts/designReviewerPrompt.ts
131
- var DESIGN_REVIEWER_PROMPT = `You are a design quality reviewer for motion graphics in CueFrame.
132
-
133
- ## Workflow
134
-
135
- 1. Call \`get_context\` to understand the current project state and brand kit.
136
- 2. Call \`get_composition\` to read the graphics themselves \u2014 a card clip carries its
137
- \`html\` and \`tokens\` verbatim; an overlay or component clip carries its params.
138
- For a component's animation code, call \`get_component_source\` with its componentId.
139
- 3. Call \`preview_frame\` with EVERY beat you need to see in ONE call \u2014 the rendered
140
- pixels, not your reading of the source.
141
- 4. Assess quality against the checklist below. If improvements are needed, send the
142
- fixes as ONE \`apply_composition\` batch \u2014 a \`clip.update\` op per graphic carrying
143
- only the fields that change \u2014 then re-preview the beats you touched to verify.
144
-
145
- ## Quality Checklist
146
-
147
- - **Visual hierarchy**: Title large/bold, subtext smaller/lighter, decorative elements subtle
148
- - **Animation choreography**: Elements arrive in sequence with staggered timing, not all at once
149
- - **Spring physics**: Use \`spring()\` for organic entrances instead of plain linear interpolation
150
- - **Color usage**: Read ALL colors from params (accentColor, textColor, backgroundColor) \u2014 never hardcode
151
- - **Entrance + exit**: Choreographed entrance sequence AND fade-out in final 15 frames
152
- - **Layered composition**: Multiple animated elements (text + accent line + shape + bg glow), not just a single element with opacity
153
- - **Typography**: Appropriate font from FONTS.*, proper letter-spacing, readable sizing
154
- - **Atmosphere**: Subtle glows, gradients, or accent color bleeds for depth
155
-
156
- ## Component Contract
157
-
158
- - Signature: \`export default function Name({ durationInFrames, params }) { ... }\`
159
- - ONLY \`useCurrentFrame()\` and \`useVideoConfig()\` hooks. NO useEffect/useState/useMemo/useCallback/useRef.
160
- - Inline styles only. No imports, no CSS files, no \`document\` access. Max 10000 chars.
161
- - All animation driven by frame number.
162
-
163
- ## Guidelines
164
-
165
- - Be specific in feedback: cite which element, which frame range, what to change.
166
- - Prefer refinement over complete rewrites \u2014 preserve the designer's intent.
167
- - A still cannot show motion. Judge timing and choreography from the source; judge
168
- layout, contrast and legibility from the frame.
169
- - After fixing, always re-preview to confirm the improvement visually.
170
- `;
171
- var DESIGN_REVIEWER_TOOLS = [
172
- "get_context",
173
- "get_composition",
174
- "get_component_source",
175
- "preview_frame",
176
- "apply_composition"
177
- ];
178
-
179
130
  // ../authoring/src/prompts/graphics.ts
180
131
  var CODE_GEN_FEW_SHOT_EXAMPLES = `
181
132
  ## Reference Examples (study these patterns, then write your component)
@@ -404,8 +355,6 @@ export {
404
355
  buildExecutionTask,
405
356
  buildPlannerUserMessage,
406
357
  PLANNING_INSTRUCTIONS,
407
- DESIGN_REVIEWER_PROMPT,
408
- DESIGN_REVIEWER_TOOLS,
409
358
  CODE_GEN_FEW_SHOT_EXAMPLES,
410
359
  COMPONENT_CONTRACT,
411
360
  TOOLKIT_REFERENCE,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  waitForJob
3
- } from "./chunk-QETYXKQQ.js";
3
+ } from "./chunk-SDCEJAO2.js";
4
4
  import {
5
5
  GENERATED_OPERATIONS,
6
6
  apiErrorFrom,
@@ -17,10 +17,10 @@ import {
17
17
  sniffImageMediaType,
18
18
  text,
19
19
  withMedia
20
- } from "./chunk-W3SIWT7J.js";
20
+ } from "./chunk-DL7WYISQ.js";
21
21
  import {
22
22
  CURATED_TOOLS
23
- } from "./chunk-AO744WIK.js";
23
+ } from "./chunk-DJW3UGBH.js";
24
24
 
25
25
  // ../mcp/src/prompts.ts
26
26
  var skillListCache = null;
@@ -91,17 +91,17 @@ CLIPPING (find the best short-form moments in a long video): \`suggest_briefs\`
91
91
 
92
92
  Every expensive step has a cheap, inspectable check \u2014 prefer reading a value over rendering and eyeballing:
93
93
  - Framing & timing are data: \`get_media_context\` BEFORE you compose.
94
- - Evidence beats guessing: \`preview_frame\` (whole-composition stills), \`preview_component\` (ONE graphic as a MOTION clip \u2014 the same bake production composites), \`preview_clip\` (a fromSec\u2192toSec window as a watchable MP4, max 60s, capture-priced \u2014 judge a cut or transition at full fidelity WITHOUT paying for a full render). These are STATELESS: nothing to open, warm, or close; concurrent previews do not contend. \`preview_frame\` defaults to the PERSISTED composition and echoes \`previewed.{source, compositionId, etag}\` \u2014 what you saw is what create_render encodes.
94
+ - Evidence beats guessing: \`preview_frame\` (whole-composition stills), \`preview_component\` (ONE authored graphic: \`executionMode:"live"\` returns a PNG image; \`executionMode:"baked"\` returns a transparent VP9 motion clip \u2014 exactly the lane production composites), \`preview_clip\` (a fromSec\u2192toSec window as a watchable MP4, max 60s, capture-priced \u2014 judge a cut or transition at full fidelity WITHOUT paying for a full render). These are STATELESS: nothing to open, warm, or close; concurrent previews do not contend. \`preview_frame\` defaults to the PERSISTED composition and echoes \`previewed.{source, compositionId, etag}\` \u2014 what you saw is what create_render encodes.
95
95
  - Quality is a number: \`score_composition\` returns scores + critique + a checkpointId; the compose result carries the winner's composite. **score vs consult**: score answers "how good IS this" (grounded numbers); \`consult\` answers "what SHOULD I change" (advice + an adoptable fix via \`select_candidate\`).
96
96
 
97
97
  ## Async model
98
98
 
99
99
  Every long job is either polled or pushed \u2014 never guessed:
100
- - \`wait_job\` kinds: \`render\`, \`compose\`, \`suggestions\`, \`verify\` (score jobs), \`preview\` (component clips), \`brand_kit_extract\`, \`consult\`. It blocks up to its window and returns a CONTINUATION when still running \u2014 re-call it.
100
+ - \`wait_job\` kinds: \`media\` (imports/generation), \`render\`, \`compose\`, \`suggestions\`, \`verify\` (score jobs), \`preview_frame\` (composition stills), \`preview\` (component image-or-motion previews), \`brand_kit_extract\`, \`consult\`. It blocks up to its window and returns a CONTINUATION when still running \u2014 re-call it.
101
101
  - Webhooks (\`create_webhook\`): ONE terminal event per kind with status INSIDE the payload \u2014 \`render.completed\`, \`compose.completed\`, \`media.completed\`, \`suggest.completed\` \u2014 plus \`checkpoint.ready\` (a held compose paused for review). Read \`cueframe://webhook-events\` for the full contract before building a receiver.
102
102
  - Presigned URLs (stills, clips, render outputs) expire \u2014 render outputs last ~7 days (refresh via the render's refresh-url op); preview stills/clips ~1 hour. Re-read for a fresh link instead of caching one.
103
103
 
104
- CUSTOM GRAPHICS \u2014 author or FORK: \`create_component\` (tsxSource) from scratch, or \`get_component_source\` on a built-in primitive (e.g. \`cinematic-title\`) to fork its editable module. Iterate author\u2192preview\u2192fix with \`preview_component\` (202 + jobId; \`wait_job(kind:"preview")\` returns the clip URL \u2014 a compile failure lands on the job's FAILED terminal carrying the sanitized compiler error) \u2192 fix via \`update_component\` \u2192 preview again. Place it via \`apply_composition\` as an \`alpha-layer\` clip \u2014 the shared renderer never runs your code (it bakes to transparent video first).
104
+ CUSTOM GRAPHICS \u2014 author or FORK: \`create_component\` (tsxSource) from scratch, or \`get_component_source\` on a built-in primitive (e.g. \`cinematic-title\`) to fork its editable module. Iterate author\u2192preview\u2192fix with \`preview_component\` (202 + jobId; \`wait_job(kind:"preview")\` returns a PNG image for \`executionMode:"live"\` or a VP9 motion URL for \`executionMode:"baked"\`; a compile failure lands on the job's FAILED terminal carrying the sanitized compiler error) \u2192 fix via \`update_component\` \u2192 preview again. Place baked components via \`apply_composition\` as an \`alpha-layer\` clip \u2014 the shared renderer never runs authored source code (it composites the transparent baked video).
105
105
 
106
106
  Cleanup: \`delete_project\` / \`delete_media\` / \`delete_webhook\` / \`delete_composition\`. \`list_projects\` re-orients you in an existing workspace; \`list_media\` (filter by \`source\`/\`tag\`) lists the library.
107
107
 
@@ -436,12 +436,16 @@ function registerCuratedTools(server, ex, opts) {
436
436
  for (const friendly of Object.keys(spec.pathArgs ?? {})) {
437
437
  inputSchema[friendly] = z.string().describe(`${friendly} (path).`);
438
438
  }
439
+ for (const [queryArg, description] of Object.entries(spec.queryArgs ?? {})) {
440
+ inputSchema[queryArg] = z.string().optional().describe(description);
441
+ }
439
442
  const bodySchema = bodySchemaFor(op);
440
443
  if (bodySchema) inputSchema.body = bodySchema;
441
444
  const annotations = { ...op.annotations, ...spec.annotations };
442
445
  server.registerTool(spec.name, { title: spec.title ?? titleCase(spec.name), description: spec.description, inputSchema, annotations }, async (args, extra) => timed(opts?.onEvent, spec.name, async (report) => {
443
446
  const a = args;
444
447
  try {
448
+ const query = Object.keys(spec.queryArgs ?? {}).filter((name) => a[name] !== void 0 && a[name] !== null && a[name] !== "").map((name) => `${encodeURIComponent(name)}=${encodeURIComponent(String(a[name]))}`).join("&");
445
449
  return await dispatchOp(ex, op, (p) => a[reverse[p]], a.body, extra, spec.name, async (res) => {
446
450
  if (spec.okText) return text(spec.okText(a));
447
451
  const json = res.text ? safeParse(res.text) : void 0;
@@ -454,17 +458,17 @@ function registerCuratedTools(server, ex, opts) {
454
458
  if (data.length) return withMedia(payload, data.map((d) => ({ data: d, kind })));
455
459
  }
456
460
  return text(payload);
457
- });
461
+ }, query || void 0);
458
462
  } catch (err) {
459
463
  return errText(`${spec.name} failed: ${fmtErr(err)}`);
460
464
  }
461
465
  }));
462
466
  }
463
467
  registerWaitJob(server, ex, opts?.waitCapMs, opts?.onEvent);
464
- registerPreviewCard(server, ex, opts?.onEvent);
468
+ registerPreviewCard(server, ex, opts?.waitCapMs, opts?.onEvent);
465
469
  }
466
- function registerPreviewCard(server, ex, onEvent) {
467
- const op = opById("previewFrame");
470
+ function registerPreviewCard(server, ex, waitCapMs, onEvent) {
471
+ const op = opById("previewFrameJob");
468
472
  server.registerTool(
469
473
  "preview_card",
470
474
  {
@@ -508,12 +512,19 @@ function registerPreviewCard(server, ex, onEvent) {
508
512
  "preview_card",
509
513
  async (res) => {
510
514
  const json = res.text ? safeParse(res.text) : void 0;
511
- const urls = (Array.isArray(json?.stills) ? json.stills : []).map(
512
- (st) => st?.url
513
- );
515
+ const jobId = json?.jobId;
516
+ if (typeof jobId !== "string" || !jobId) {
517
+ return errText("preview_card enqueue returned no jobId");
518
+ }
519
+ const waitMs = Math.min(waitCapMs ?? 3e4, 3e4);
520
+ const done = await waitForJob(ex, "preview_frame", jobId, void 0, Date.now() + waitMs);
521
+ if (!done.ok) return errText(done.text);
522
+ if (done.stillRunning) return text(`${done.text}
523
+ jobId: ${jobId}`);
524
+ const urls = done.mediaUrls ?? [];
514
525
  const data = await fetchPreviews(urls, 2);
515
526
  report({ preview: { urls: urls.filter(Boolean).length, fetched: data.length } });
516
- const payload = res.text || `previewed card (${a.aspectRatio ?? "9:16"})`;
527
+ const payload = done.text || `previewed card (${a.aspectRatio ?? "9:16"})`;
517
528
  return data.length ? withMedia(payload, data.map((d) => ({ data: d, kind: "image" }))) : text(payload);
518
529
  }
519
530
  );
@@ -529,10 +540,10 @@ function registerWaitJob(server, ex, waitCapMs, onEvent) {
529
540
  {
530
541
  title: "Wait for Job",
531
542
  annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
532
- description: "Wait for a long-running job and return the resolved result \u2014 a BOUNDED long-poll. Polls the job status (render / compose / consult / clip-suggestions / verify) and blocks up to the transport window (30s on the hosted transport); if the job is still running at the window it returns a `Still running` continuation \u2014 call wait_job again with the same arguments to keep waiting (the job keeps executing server-side; nothing is lost between calls). Call this right after compose / create_render / consult / suggest_briefs / score_composition / preview_component. For event-driven fan-out, create_webhook delivers the terminal instead.",
543
+ description: "Wait for a long-running job and return the resolved result \u2014 a BOUNDED long-poll. Polls job status (media import/generation / render / compose / consult / clip-suggestions / verify / preview-frame) and blocks up to the transport window (30s on the hosted transport); if still running, it returns a continuation \u2014 call wait_job again with the same arguments (the job keeps executing server-side). Call this after import_media / generate_media / finalize_upload / import_resource / compose / create_render / consult / suggest_briefs / score_composition / preview_frame / preview_component. For event-driven fan-out, create_webhook delivers the terminal instead.",
533
544
  inputSchema: {
534
- kind: z.enum(["render", "suggestions", "compose", "verify", "preview", "brand_kit_extract", "consult"]).describe("What to wait on: a render job, a compose job, a consult advisory, AI clip-suggestion analysis, or a generic async job (verify / preview / brand-kit extract \u2014 the kind is named in the enqueue receipt)."),
535
- id: z.string().describe('kind="render": renderId. kind="compose": composeJobId. kind="consult": the consultJobId from the consult receipt (surfaces the advisory envelope \u2014 assessment, proposals, principles). kind="suggestions": mediaItemId. kind="verify"/"preview"/"brand_kit_extract": the jobId from the enqueue receipt.'),
545
+ kind: z.enum(["media", "render", "suggestions", "compose", "verify", "preview_frame", "preview", "brand_kit_extract", "consult"]).describe("What to wait on: media ingest/generation, render, compose, consult, clip-suggestion analysis, or a generic async job (verify / preview_frame / preview / brand-kit extract \u2014 use the enqueue receipt kind)."),
546
+ id: z.string().describe('kind="media": mediaItemId returned by import/generate/finalize/import_resource. kind="render": renderId. kind="compose": composeJobId. kind="consult": consultJobId. kind="suggestions": mediaItemId. Generic kinds use the jobId from the enqueue receipt.'),
536
547
  projectId: z.string().optional().describe('Required when kind="render", "compose", or "consult".'),
537
548
  timeoutMs: z.number().int().min(1e3).max(30 * 60 * 1e3).optional().describe("Maximum wait in ms (default 30 min for render/compose, 5 min for suggestions).")
538
549
  }
@@ -542,7 +553,7 @@ function registerWaitJob(server, ex, waitCapMs, onEvent) {
542
553
  if ((kind === "render" || kind === "compose" || kind === "consult") && !args.projectId) {
543
554
  return errText(`wait_job(kind="${kind}") requires a projectId.`);
544
555
  }
545
- const defaultCap = kind === "suggestions" ? 5 * 60 * 1e3 : 30 * 60 * 1e3;
556
+ const defaultCap = kind === "suggestions" || kind === "media" ? 5 * 60 * 1e3 : 30 * 60 * 1e3;
546
557
  const requested = args.timeoutMs ?? defaultCap;
547
558
  const deadline = Date.now() + (waitCapMs ? Math.min(requested, waitCapMs) : requested);
548
559
  const res = await waitForJob(ex, kind, args.id, args.projectId, deadline);
@@ -20,7 +20,7 @@ import {
20
20
  scoreAndRank,
21
21
  segmentShots,
22
22
  stabilizeSelectionHysteresis
23
- } from "./chunk-XQ72DZKJ.js";
23
+ } from "./chunk-ZPRBGW4Y.js";
24
24
  import {
25
25
  flattenCompoundClips,
26
26
  hasCompoundClips
@@ -36,7 +36,7 @@ import {
36
36
  import {
37
37
  CueframeError,
38
38
  encodeError
39
- } from "./chunk-LLUW26BS.js";
39
+ } from "./chunk-AW57IWNW.js";
40
40
 
41
41
  // ../execution/core/src/render/emphasis.ts
42
42
  function buildEmphasisSet(emphasisWords) {
@@ -5,7 +5,7 @@ import {
5
5
  isOk,
6
6
  opById,
7
7
  safeParse
8
- } from "./chunk-W3SIWT7J.js";
8
+ } from "./chunk-DL7WYISQ.js";
9
9
 
10
10
  // ../mcp/src/wait.ts
11
11
  var defaultSleep = (ms) => new Promise((r) => setTimeout(r, ms));
@@ -14,7 +14,47 @@ var DEFAULT_POLL_MS = 3e3;
14
14
  function fmtTime(sec) {
15
15
  return `${Math.floor(sec / 60)}:${String(Math.floor(sec % 60)).padStart(2, "0")}`;
16
16
  }
17
+ function describeProgress(json, nowMs) {
18
+ const status = json?.processingStatus?.phase ?? json?.status;
19
+ const phase = json?.progress?.phase;
20
+ const percent = json?.processingStatus?.percent ?? json?.progress?.percent;
21
+ const updatedAt = json?.updatedAt ?? json?.progress?.updatedAt;
22
+ const parts = [];
23
+ if (typeof status === "string" && status) parts.push(`Last status: ${status}`);
24
+ if (typeof phase === "string" && phase && phase !== status) parts.push(`phase: ${phase}`);
25
+ if (typeof percent === "number" && Number.isFinite(percent)) parts.push(`progress: ${percent}%`);
26
+ if (typeof updatedAt === "string" && updatedAt) {
27
+ parts.push(`updatedAt: ${updatedAt}`);
28
+ const parsed = Date.parse(updatedAt);
29
+ if (Number.isFinite(parsed) && nowMs >= parsed) {
30
+ const staleSec = Math.floor((nowMs - parsed) / 1e3);
31
+ if (staleSec >= 60) parts.push(`unchanged for ~${fmtTime(staleSec)}`);
32
+ }
33
+ }
34
+ return parts.join("; ");
35
+ }
17
36
  var KINDS = {
37
+ media: {
38
+ operationId: "getMedia",
39
+ mapArg: (_p, id) => id,
40
+ terminal: (j) => {
41
+ const phase = String(j?.processingStatus?.phase ?? j?.status ?? "");
42
+ if (phase === "complete" || phase === "completed" || phase === "ready") {
43
+ const lines = ["Media ready."];
44
+ if (j?.id) lines.push(`Media ID: ${j.id}`);
45
+ if (j?.name) lines.push(`Name: ${j.name}`);
46
+ if (typeof j?.duration === "number") lines.push(`Duration: ${j.duration.toFixed(2)}s`);
47
+ if (j?.mimeType) lines.push(`Type: ${j.mimeType}`);
48
+ lines.push("\nUse this media ID with get_media_context, suggest_briefs, or as a composition source.");
49
+ return { ok: true, text: lines.join("\n") };
50
+ }
51
+ if (phase === "error" || phase === "failed" || phase === "cancelled") {
52
+ const cause = j?.processingStatus?.error ?? j?.processingStatus?.message ?? j?.error ?? "";
53
+ return { ok: false, text: `Media ${phase}${cause ? `: ${typeof cause === "string" ? cause : JSON.stringify(cause)}` : ""}.` };
54
+ }
55
+ return null;
56
+ }
57
+ },
18
58
  render: {
19
59
  operationId: "getRender",
20
60
  mapArg: (p, id, projectId) => p === "renderId" ? id : projectId,
@@ -33,9 +73,15 @@ Download URL: ${url}`);
33
73
  const lines = [`Render ${s}${cause ? `: ${cause}` : ""}.`];
34
74
  if (j?.errorCode) lines.push(`Code: ${j.errorCode}${j?.category ? ` (${j.category})` : ""}`);
35
75
  if (typeof j?.retryable === "boolean") {
36
- lines.push(
37
- j.retryable ? "retryable: true \u2014 transient pipeline failure; call retry_render to re-attempt." : `retryable: false \u2014 deterministic defect${j?.category ? ` (category ${j.category})` : ""}; fix the composition before re-rendering \u2014 retry_render alone will not help.`
38
- );
76
+ if (j?.category === "internal") {
77
+ lines.push(
78
+ `retryable: ${j.retryable} \u2014 Cueframe reported an INTERNAL pipeline defect. The composition has not been proven invalid; do not mutate it to work around this failure. Correlate the renderId/requestId in Axiom or Sentry and fix the failing pipeline stage.`
79
+ );
80
+ } else {
81
+ lines.push(
82
+ j.retryable ? "retryable: true \u2014 transient pipeline failure; call retry_render to re-attempt." : `retryable: false \u2014 deterministic defect${j?.category ? ` (category ${j.category})` : ""}; fix the composition before re-rendering \u2014 retry_render alone will not help.`
83
+ );
84
+ }
39
85
  }
40
86
  return { ok: false, text: lines.join("\n") };
41
87
  }
@@ -219,7 +265,35 @@ Worst-first critique: ${r.critique}`);
219
265
  lines.push("\nFix the lowest criterion via apply_composition, then re-verify.");
220
266
  return { ok: true, text: lines.join("\n") };
221
267
  }
222
- if (s === "failed") return jobFailedResult("Verify", "score_composition", j);
268
+ if (s === "failed" || s === "cancelled") return jobFailedResult("Verify", "score_composition", j);
269
+ return null;
270
+ }
271
+ },
272
+ preview_frame: {
273
+ operationId: "getJob",
274
+ mapArg: (_p, id) => id,
275
+ terminal: (j) => {
276
+ const status = String(j?.status ?? "");
277
+ if (status === "succeeded") {
278
+ const result = j?.result ?? {};
279
+ const artifacts = Array.isArray(result.artifacts) ? result.artifacts : [];
280
+ const urls = artifacts.map((artifact) => artifact.url).filter((url) => typeof url === "string" && url.length > 0);
281
+ const lines = [`Preview-frame complete: ${artifacts.length} artifact(s).`];
282
+ for (const artifact of artifacts) {
283
+ lines.push(
284
+ `- ${typeof artifact.beatSec === "number" ? `${artifact.beatSec.toFixed(2)}s` : artifact.id ?? "frame"}${artifact.url ? ` \u2014 ${artifact.url}` : " \u2014 missing presigned URL"}`
285
+ );
286
+ }
287
+ lines.push(`
288
+ Snapshot provenance: ${JSON.stringify(result.previewed ?? {})}`);
289
+ lines.push(`Geometry: ${JSON.stringify(result.geometry ?? {})}`);
290
+ if (result.warnings?.length) lines.push(`Warnings: ${JSON.stringify(result.warnings)}`);
291
+ lines.push("\nThe images ride with this result; judge the pixels and use layers/geometry as evidence.");
292
+ return { ok: urls.length === artifacts.length && artifacts.length > 0, text: lines.join("\n"), mediaUrls: urls };
293
+ }
294
+ if (status === "failed" || status === "cancelled") {
295
+ return jobFailedResult("Preview-frame", "preview_frame", j);
296
+ }
223
297
  return null;
224
298
  }
225
299
  },
@@ -230,18 +304,23 @@ Worst-first critique: ${r.critique}`);
230
304
  const s = String(j?.status ?? "");
231
305
  if (s === "succeeded") {
232
306
  const r = j?.result ?? {};
307
+ const isImage = r.artifactKind === "image" || r.contentType?.startsWith("image/") === true || !r.artifactKind && !r.contentType && /\.(?:png|jpe?g|webp)(?:\?|$)/i.test(r.url ?? "");
308
+ const label = isImage ? "Image" : r.artifactKind === "motion" ? "Motion clip" : "Artifact";
233
309
  return {
234
310
  ok: true,
235
- mediaUrls: r.url ? [r.url] : void 0,
311
+ // MCP image blocks are image-only. Motion remains a truthful URL;
312
+ // attaching WebM bytes as an image corrupts the model-facing media type.
313
+ mediaUrls: r.url && isImage ? [r.url] : void 0,
236
314
  text: r.url ? `Preview ready.
237
315
 
238
- Clip: ${r.url}${r.urlExpiresAt ? `
316
+ ${label}: ${r.url}${r.contentType ? `
317
+ Content-Type: ${r.contentType}` : ""}${r.urlExpiresAt ? `
239
318
  (link valid until ${r.urlExpiresAt})` : ""}
240
319
 
241
320
  Inspect it, fix the component via create_component if needed, and re-preview.` : "Preview succeeded but returned no url \u2014 inspect GET /v1/jobs for the raw result."
242
321
  };
243
322
  }
244
- if (s === "failed") return jobFailedResult("Preview", "preview_component", j);
323
+ if (s === "failed" || s === "cancelled") return jobFailedResult("Preview", "preview_component", j);
245
324
  return null;
246
325
  }
247
326
  },
@@ -270,10 +349,14 @@ Review the tokens, then create_brand_kit to persist a kit. (0 tokens usually mea
270
349
  }
271
350
  };
272
351
  function jobFailedResult(label, reEnqueueTool, j) {
273
- const code = String(j?.error?.code ?? "unknown");
352
+ const cancelled = j?.status === "cancelled";
353
+ const code = String(j?.error?.code ?? (cancelled ? "cancelled" : "unknown"));
274
354
  const msg = typeof j?.error?.message === "string" ? j.error.message : "";
275
- const retryHint = code === "job_timeout" ? ` The executor died mid-run and the stall sweep reaped the job \u2014 re-enqueue ${reEnqueueTool} to retry.` : "";
276
- return { ok: false, text: `${label} failed (${code})${msg ? `: ${msg}` : ""}.${retryHint}` };
355
+ const retryHint = code === "job_timeout" ? ` The executor died mid-run and the stall sweep reaped the job \u2014 inspect this jobId in Axiom/Sentry before retrying; re-enqueue ${reEnqueueTool} only after the failing pipeline stage is healthy.` : "";
356
+ return {
357
+ ok: false,
358
+ text: `${label} ${cancelled ? "cancelled" : "failed"} (${code})${msg ? `: ${msg}` : ""}.${retryHint}`
359
+ };
277
360
  }
278
361
  async function waitForJob(ex, kind, id, projectId, deadline, deps = {}) {
279
362
  const sleep = deps.sleep ?? defaultSleep;
@@ -281,7 +364,7 @@ async function waitForJob(ex, kind, id, projectId, deadline, deps = {}) {
281
364
  const pollMs = deps.pollMs ?? DEFAULT_POLL_MS;
282
365
  const cfg = KINDS[kind];
283
366
  const op = opById(cfg.operationId);
284
- let lastStatus = "";
367
+ let lastProgress = "";
285
368
  const INVOKE_BUDGET_MS = deps.invokeBudgetMs ?? 2e3;
286
369
  let firstPoll = true;
287
370
  while (firstPoll || now() + INVOKE_BUDGET_MS < deadline) {
@@ -300,12 +383,12 @@ async function waitForJob(ex, kind, id, projectId, deadline, deps = {}) {
300
383
  const json = safeParse(res.text);
301
384
  const t = cfg.terminal(json);
302
385
  if (t) return t;
303
- if (json && typeof json.status === "string") lastStatus = json.status;
386
+ lastProgress = describeProgress(json, now());
304
387
  }
305
388
  if (now() + pollMs + INVOKE_BUDGET_MS >= deadline) break;
306
389
  await sleep(pollMs);
307
390
  }
308
- const tail = lastStatus ? ` Last status: ${lastStatus}.` : "";
391
+ const tail = lastProgress ? ` ${lastProgress}.` : "";
309
392
  return {
310
393
  ok: true,
311
394
  stillRunning: true,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ChatErrorView,
3
3
  DirectorTurnContext
4
- } from "./chunk-ZPLJ24OV.js";
4
+ } from "./chunk-TO4BFNLJ.js";
5
5
  import {
6
6
  GenerationArtifact
7
7
  } from "./chunk-73DQTUWY.js";
@@ -9,7 +9,7 @@ import {
9
9
  import {
10
10
  decodeError,
11
11
  scrubSensitive
12
- } from "./chunk-LLUW26BS.js";
12
+ } from "./chunk-AW57IWNW.js";
13
13
 
14
14
  // ../director/src/domain/chat.ts
15
15
  import { z } from "zod";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolveBookendTimeline
3
- } from "./chunk-VHF66LCQ.js";
3
+ } from "./chunk-NQSMEUJ6.js";
4
4
 
5
5
  // ../execution/compose/src/tokenResolver.ts
6
6
  var DEFAULTS = {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  CueframeError,
3
3
  encodeError
4
- } from "./chunk-LLUW26BS.js";
4
+ } from "./chunk-AW57IWNW.js";
5
5
 
6
6
  // ../execution/core/src/render/vcam/constants.ts
7
7
  var P_MIN = 0.5;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolvePrimitive
3
- } from "../chunk-CAJQ7H5A.js";
3
+ } from "../chunk-HBVAZXYO.js";
4
4
  import "../chunk-H5LMJKZU.js";
5
5
  import "../chunk-MFHXCHRI.js";
6
6
  import "../chunk-JQMPHKLU.js";
@@ -33,7 +33,7 @@ import "../chunk-JF4JJAFP.js";
33
33
  import {
34
34
  CueframeError,
35
35
  encodeError
36
- } from "../chunk-LLUW26BS.js";
36
+ } from "../chunk-AW57IWNW.js";
37
37
  import "../chunk-2ESYSVXG.js";
38
38
 
39
39
  // ../execution/compose/src/CompositionRenderer.tsx
package/dist/compose.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  resolveTokens,
3
3
  sceneToRenderInput
4
- } from "./chunk-VFMW3JUY.js";
4
+ } from "./chunk-TXSFYUZH.js";
5
5
  import {
6
6
  allCatalogs,
7
7
  getPrimitiveSubtext,
@@ -13,7 +13,7 @@ import {
13
13
  resetPrimitiveOverrides,
14
14
  resolvePrimitive,
15
15
  resolveTransitionPresentation
16
- } from "./chunk-CAJQ7H5A.js";
16
+ } from "./chunk-HBVAZXYO.js";
17
17
  import "./chunk-H5LMJKZU.js";
18
18
  import "./chunk-MFHXCHRI.js";
19
19
  import "./chunk-JQMPHKLU.js";
@@ -42,9 +42,9 @@ import {
42
42
  getPrimitiveTextParam,
43
43
  listPrimitivesByCategory
44
44
  } from "./chunk-DCVJWGIA.js";
45
- import "./chunk-VHF66LCQ.js";
45
+ import "./chunk-NQSMEUJ6.js";
46
46
  import "./chunk-QH3YI3ND.js";
47
- import "./chunk-XQ72DZKJ.js";
47
+ import "./chunk-ZPRBGW4Y.js";
48
48
  import "./chunk-23HFEKV7.js";
49
49
  import "./chunk-VZ7TYX6Z.js";
50
50
  import "./chunk-7PA7FGLD.js";
@@ -52,7 +52,7 @@ import "./chunk-KYRDKK2D.js";
52
52
  import "./chunk-JF4JJAFP.js";
53
53
  import "./chunk-DENF4TPI.js";
54
54
  import "./chunk-WREYUH2E.js";
55
- import "./chunk-LLUW26BS.js";
55
+ import "./chunk-AW57IWNW.js";
56
56
  import "./chunk-2ESYSVXG.js";
57
57
  export {
58
58
  allCatalogs,
@@ -30,7 +30,7 @@ import {
30
30
  silhouetteKeepOutForWindow,
31
31
  sourceRectToOutput,
32
32
  sourceWindowKey
33
- } from "../chunk-PIURX6IZ.js";
33
+ } from "../chunk-GIA2SVVB.js";
34
34
  import {
35
35
  BRAND_TOKEN_REFS,
36
36
  BRAND_TOKEN_ROOT_KEYS,
@@ -71,7 +71,7 @@ import {
71
71
  apcaLc
72
72
  } from "../chunk-DSMLHYJ4.js";
73
73
  import "../chunk-JF4JJAFP.js";
74
- import "../chunk-LLUW26BS.js";
74
+ import "../chunk-AW57IWNW.js";
75
75
  import "../chunk-2ESYSVXG.js";
76
76
  export {
77
77
  BEHIND_BAND,
@@ -6,9 +6,9 @@ import {
6
6
  } from "./chunk-ICSZF37W.js";
7
7
  import {
8
8
  playableSpans
9
- } from "./chunk-VHF66LCQ.js";
9
+ } from "./chunk-NQSMEUJ6.js";
10
10
  import "./chunk-QH3YI3ND.js";
11
- import "./chunk-XQ72DZKJ.js";
11
+ import "./chunk-ZPRBGW4Y.js";
12
12
  import "./chunk-23HFEKV7.js";
13
13
  import "./chunk-VZ7TYX6Z.js";
14
14
  import "./chunk-7PA7FGLD.js";
@@ -30,7 +30,7 @@ import {
30
30
  } from "./chunk-2B5VJZHL.js";
31
31
  import "./chunk-DENF4TPI.js";
32
32
  import "./chunk-WREYUH2E.js";
33
- import "./chunk-LLUW26BS.js";
33
+ import "./chunk-AW57IWNW.js";
34
34
  import "./chunk-2ESYSVXG.js";
35
35
 
36
36
  // ../composition-ops/src/index.ts
@@ -44,7 +44,7 @@ import {
44
44
  silhouetteKeepOutForWindow,
45
45
  sourceRectToOutput,
46
46
  sourceWindowKey
47
- } from "./chunk-PIURX6IZ.js";
47
+ } from "./chunk-GIA2SVVB.js";
48
48
  import {
49
49
  BRAND_TOKEN_REFS,
50
50
  BRAND_TOKEN_ROOT_KEYS,
@@ -190,7 +190,7 @@ import {
190
190
  isSourceKindCompatible
191
191
  } from "./chunk-DENF4TPI.js";
192
192
  import "./chunk-WREYUH2E.js";
193
- import "./chunk-LLUW26BS.js";
193
+ import "./chunk-AW57IWNW.js";
194
194
  import "./chunk-2ESYSVXG.js";
195
195
 
196
196
  // ../composition/src/color-grade.ts
@@ -42,20 +42,20 @@ import {
42
42
  sliceTranscriptWords,
43
43
  splitIntoSentences,
44
44
  validateComposition
45
- } from "../chunk-VHF66LCQ.js";
45
+ } from "../chunk-NQSMEUJ6.js";
46
46
  import {
47
47
  buildEasedZooms,
48
48
  buildPannedCenters,
49
49
  easeOutCubic
50
50
  } from "../chunk-QH3YI3ND.js";
51
- import "../chunk-XQ72DZKJ.js";
51
+ import "../chunk-ZPRBGW4Y.js";
52
52
  import "../chunk-23HFEKV7.js";
53
53
  import "../chunk-VZ7TYX6Z.js";
54
54
  import "../chunk-7PA7FGLD.js";
55
55
  import "../chunk-KYRDKK2D.js";
56
56
  import "../chunk-DENF4TPI.js";
57
57
  import "../chunk-WREYUH2E.js";
58
- import "../chunk-LLUW26BS.js";
58
+ import "../chunk-AW57IWNW.js";
59
59
  import "../chunk-2ESYSVXG.js";
60
60
  export {
61
61
  CARD_BOOKEND_DEFAULT_MS,
@@ -7,8 +7,8 @@ import {
7
7
  stabilizeIncumbentChallenger,
8
8
  stabilizePresenceGate,
9
9
  stabilizeSelectionHysteresis
10
- } from "../chunk-XQ72DZKJ.js";
11
- import "../chunk-LLUW26BS.js";
10
+ } from "../chunk-ZPRBGW4Y.js";
11
+ import "../chunk-AW57IWNW.js";
12
12
  import "../chunk-2ESYSVXG.js";
13
13
 
14
14
  // ../execution/core/src/select/errorCodes.ts
package/dist/core.js CHANGED
@@ -10,16 +10,16 @@ import {
10
10
  ensureEven,
11
11
  extractCaptionWordsFromDoc,
12
12
  isEmphasized
13
- } from "./chunk-VHF66LCQ.js";
13
+ } from "./chunk-NQSMEUJ6.js";
14
14
  import "./chunk-QH3YI3ND.js";
15
- import "./chunk-XQ72DZKJ.js";
15
+ import "./chunk-ZPRBGW4Y.js";
16
16
  import "./chunk-23HFEKV7.js";
17
17
  import "./chunk-VZ7TYX6Z.js";
18
18
  import "./chunk-7PA7FGLD.js";
19
19
  import "./chunk-KYRDKK2D.js";
20
20
  import "./chunk-DENF4TPI.js";
21
21
  import "./chunk-WREYUH2E.js";
22
- import "./chunk-LLUW26BS.js";
22
+ import "./chunk-AW57IWNW.js";
23
23
  import "./chunk-2ESYSVXG.js";
24
24
  export {
25
25
  DEFAULT_FPS,
@@ -10,13 +10,13 @@ import {
10
10
  dataChunk,
11
11
  generationArtifactFromToolResult,
12
12
  projectDirectorHistory
13
- } from "../chunk-LJ5W4ZBU.js";
14
- import "../chunk-ZPLJ24OV.js";
13
+ } from "../chunk-TMB5AY6Q.js";
14
+ import "../chunk-TO4BFNLJ.js";
15
15
  import "../chunk-73DQTUWY.js";
16
16
  import "../chunk-BADZHXLR.js";
17
17
  import "../chunk-U3JPILZS.js";
18
18
  import "../chunk-XELS2BGA.js";
19
- import "../chunk-LLUW26BS.js";
19
+ import "../chunk-AW57IWNW.js";
20
20
  import "../chunk-2ESYSVXG.js";
21
21
  export {
22
22
  CueFrameIteration,
@@ -9,7 +9,7 @@ import {
9
9
  ProjectRef,
10
10
  chatErrorViewFromEnvelope,
11
11
  chatErrorViewFromUnknown
12
- } from "../chunk-ZPLJ24OV.js";
12
+ } from "../chunk-TO4BFNLJ.js";
13
13
  import {
14
14
  ClientRequestId,
15
15
  GenerateMediaCommand,
@@ -31,7 +31,7 @@ import {
31
31
  import "../chunk-BADZHXLR.js";
32
32
  import "../chunk-U3JPILZS.js";
33
33
  import "../chunk-XELS2BGA.js";
34
- import "../chunk-LLUW26BS.js";
34
+ import "../chunk-AW57IWNW.js";
35
35
  import "../chunk-2ESYSVXG.js";
36
36
  export {
37
37
  ChatErrorView,