@cueframe/kernel 0.2.32 → 0.2.34

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 (56) hide show
  1. package/dist/_members/errors/registry.d.ts +4 -0
  2. package/dist/_members/render-harness/assetRefs.d.ts +26 -0
  3. package/dist/_members/render-harness/assetRefs.d.ts.map +1 -0
  4. package/dist/_members/render-harness/cardAssetAdmission.d.ts.map +1 -1
  5. package/dist/_members/render-harness/cardFonts.d.ts +13 -0
  6. package/dist/_members/render-harness/cardFonts.d.ts.map +1 -0
  7. package/dist/_members/render-harness/cardRender.d.ts +1 -0
  8. package/dist/_members/render-harness/cardRender.d.ts.map +1 -1
  9. package/dist/_members/render-harness/css-tree-subpaths.d.ts +5 -0
  10. package/dist/_members/render-harness/renderInputAssets.d.ts.map +1 -1
  11. package/dist/authoring.js +2 -2
  12. package/dist/{chunk-LLC6TCH5.js → chunk-3GNTA646.js} +1 -1
  13. package/dist/{chunk-LEJ5QXHP.js → chunk-4RREA7VA.js} +7 -6
  14. package/dist/{chunk-3OOMVQ6I.js → chunk-5YO4LAB7.js} +2 -2
  15. package/dist/{chunk-WYKUWRQG.js → chunk-A3MXR6JI.js} +33 -1
  16. package/dist/{chunk-F5B6OM73.js → chunk-ANNB4VC6.js} +1283 -1271
  17. package/dist/{chunk-T4XTC35J.js → chunk-DLKCGEKP.js} +1 -1
  18. package/dist/{chunk-Q244EHRI.js → chunk-GMVUJYPM.js} +1 -1
  19. package/dist/{chunk-MN6D3U5N.js → chunk-KSRFYFUZ.js} +8 -1
  20. package/dist/{chunk-JGXJEY77.js → chunk-NJOWIGUL.js} +3 -3
  21. package/dist/chunk-OSMXQV5V.js +18 -0
  22. package/dist/chunk-RAPDICTC.js +82 -0
  23. package/dist/{chunk-NSXFYDBP.js → chunk-TCYULWNP.js} +1 -1
  24. package/dist/{chunk-AZSTZE64.js → chunk-W44ASS4N.js} +6 -6
  25. package/dist/{chunk-JTVHOHT6.js → chunk-YOE5Y2SJ.js} +1 -1
  26. package/dist/compose.js +20 -20
  27. package/dist/composition/projection.js +2 -2
  28. package/dist/composition-ops.js +5 -5
  29. package/dist/composition.js +2 -2
  30. package/dist/core/render.js +3 -3
  31. package/dist/core/select.js +2 -2
  32. package/dist/core.js +3 -3
  33. package/dist/director/ai-sdk.js +3 -3
  34. package/dist/director/domain.js +2 -2
  35. package/dist/director.js +3 -3
  36. package/dist/errors.js +3 -1
  37. package/dist/mcp/adapter.js +3 -3
  38. package/dist/mcp/core.js +1 -1
  39. package/dist/mcp/curation.js +1 -1
  40. package/dist/mcp/server.js +4 -4
  41. package/dist/mcp.js +4 -4
  42. package/dist/primitives/hero-text.js +2 -2
  43. package/dist/primitives/lib/index.js +6 -6
  44. package/dist/primitives/lib.js +6 -6
  45. package/dist/primitives/scenes.js +2 -2
  46. package/dist/primitives/text.js +3 -3
  47. package/dist/primitives.js +18 -18
  48. package/dist/render-harness/cardAssetAdmission.js +3 -2
  49. package/dist/render-harness/cardFonts.d.ts +1 -0
  50. package/dist/render-harness/cardFonts.js +13 -0
  51. package/dist/render-harness/renderInputAssets.js +2 -1
  52. package/dist/render-harness.js +28 -7
  53. package/package.json +17 -13
  54. package/dist/{chunk-ZDL7XEXW.js → chunk-RBWS5XHE.js} +7 -7
  55. package/dist/{chunk-7SQOXIWR.js → chunk-RL5SO653.js} +3 -3
  56. package/dist/{chunk-IAQHWJUO.js → chunk-TE3PNQG6.js} +4 -4
@@ -5,6 +5,8 @@ export interface ErrorSpec {
5
5
  category: ErrorCategory;
6
6
  retryable: boolean;
7
7
  httpStatus: number;
8
+ /** Overrides the derived wait; see `retryAfterSecondsFor`. */
9
+ retryAfterSeconds?: number;
8
10
  }
9
11
  export declare const ERROR_CODES: {
10
12
  readonly unauthorized: {
@@ -1649,6 +1651,8 @@ export declare class CueframeError extends Error {
1649
1651
  export declare function encodeError(e: CueframeError): string;
1650
1652
  export declare function decodeError(msg: string): CueframeError | null;
1651
1653
  export declare function scrubSensitive(s: string): string;
1654
+ /** Seconds to wait before retrying, or undefined when retrying will not help. */
1655
+ export declare function retryAfterSecondsFor(code: ErrorCode): number | undefined;
1652
1656
  export declare function toWireEnvelope(e: Envelope, opts?: {
1653
1657
  trusted?: boolean;
1654
1658
  }): Envelope;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * What counts as a reference to something OUTSIDE this document.
3
+ *
4
+ * Two guards ask that question about card HTML — `cardAssetAdmission`'s CSS/HTML
5
+ * walk and `renderInputAssets`'s `suspiciousUnannotatedAsset` sweep — and they
6
+ * disagreed. The walk knew that `url(#local-id)` is a same-document fragment;
7
+ * the sweep matched a bare `url(` and refused it.
8
+ *
9
+ * The visible cost: an inline `<svg>` using `clip-path="url(#mark-clip)"` passed
10
+ * the guard that understands SVG and was refused by the one that does not, so the
11
+ * org's own logo could not be inlined without rewriting it (CUE-31 sibling,
12
+ * reported 2026-09-17). A fragment reference is the OPPOSITE of remote — it
13
+ * cannot leave the document — and every guard has to agree on that.
14
+ *
15
+ * One definition, imported by both.
16
+ */
17
+ /** `url(#id)`, `href="#id"` — resolves inside this document, never over a network. */
18
+ export declare function isFragmentReference(value: string): boolean;
19
+ /** Every `url(...)` payload in a CSS value, unquoted. */
20
+ export declare function cssUrlPayloads(value: string): string[];
21
+ /**
22
+ * Does this CSS value reach outside the document? True only when it carries a
23
+ * `url()` whose payload is not a same-document fragment.
24
+ */
25
+ export declare function hasNonFragmentCssUrl(value: string): boolean;
26
+ //# sourceMappingURL=assetRefs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assetRefs.d.ts","sourceRoot":"","sources":["../src/assetRefs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,sFAAsF;AACtF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED,yDAAyD;AACzD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAEtD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAI3D"}
@@ -1 +1 @@
1
- {"version":3,"file":"cardAssetAdmission.d.ts","sourceRoot":"","sources":["../src/cardAssetAdmission.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AA+GzD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAQhE"}
1
+ {"version":3,"file":"cardAssetAdmission.d.ts","sourceRoot":"","sources":["../src/cardAssetAdmission.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AA4GzD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAQhE"}
@@ -0,0 +1,13 @@
1
+ /** The `font-family` stacks a card's HTML declares, deduplicated. */
2
+ export declare function cardFontFamilyStacks(html: string): string[];
3
+ /**
4
+ * The bundled families a card's HTML names, in the order a renderer should load them.
5
+ *
6
+ * The loader half of the same question `assertCardFontsAdmitted` gates on, off the
7
+ * same extraction, so the faces a card is ALLOWED to name and the faces a renderer
8
+ * actually registers cannot drift apart. Entries that are not bundled (a generic,
9
+ * a system face) are dropped: there is nothing to load for them.
10
+ */
11
+ export declare function cardBundledFamilies(html: string): string[];
12
+ export declare function assertCardFontsAdmitted(html: string, locator: string): void;
13
+ //# sourceMappingURL=cardFonts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cardFonts.d.ts","sourceRoot":"","sources":["../src/cardFonts.ts"],"names":[],"mappings":"AAqEA,qEAAqE;AACrE,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAI3D;AAmCD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ1D;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAa3E"}
@@ -5,6 +5,7 @@ export declare function generateCardRootSource(opts: {
5
5
  width: number;
6
6
  height: number;
7
7
  fps: number;
8
+ renderEntryRoot: string;
8
9
  }): string;
9
10
  export declare function generateCardEntrySource(): string;
10
11
  export declare function buildCardWebpackOverride(renderEntryRoot: string): (config: any) => any;
@@ -1 +1 @@
1
- {"version":3,"file":"cardRender.d.ts","sourceRoot":"","sources":["../src/cardRender.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AACvD,eAAO,MAAM,kBAAkB,wBAAwB,CAAC;AACxD,eAAO,MAAM,mBAAmB,yBAAyB,CAAC;AAE1D,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CA6BnG;AAED,wBAAgB,uBAAuB,IAAI,MAAM,CAMhD;AAED,wBAAgB,wBAAwB,CAAC,eAAe,EAAE,MAAM,IACtD,QAAQ,GAAG,SAOpB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CA0D7F"}
1
+ {"version":3,"file":"cardRender.d.ts","sourceRoot":"","sources":["../src/cardRender.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AACvD,eAAO,MAAM,kBAAkB,wBAAwB,CAAC;AACxD,eAAO,MAAM,mBAAmB,yBAAyB,CAAC;AAE1D,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,EAAE,MAAM,CAAC;CACzB,GAAG,MAAM,CAkDT;AAED,wBAAgB,uBAAuB,IAAI,MAAM,CAMhD;AAED,wBAAgB,wBAAwB,CAAC,eAAe,EAAE,MAAM,IACtD,QAAQ,GAAG,SAOpB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAgE7F"}
@@ -9,3 +9,8 @@ declare module 'css-tree/walker' {
9
9
  const walk: typeof import('css-tree').walk;
10
10
  export default walk;
11
11
  }
12
+
13
+ declare module 'css-tree/generator' {
14
+ const generate: typeof import('css-tree').generate;
15
+ export default generate;
16
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"renderInputAssets.d.ts","sourceRoot":"","sources":["../src/renderInputAssets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGzD,MAAM,MAAM,SAAS,GACjB,QAAQ,GACR,OAAO,GACP,YAAY,GACZ,OAAO,GACP,cAAc,GACd,MAAM,GACN,YAAY,GACZ,gBAAgB,CAAC;AAErB,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,SAAS,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAM/C;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,IAAI,MAAM,GAAG,SAAS,CAAC;IAC1B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AA8GD,wBAAiB,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,SAAS,CAAC,SAAS,CAAC,CAoDpE;AAsBD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,QAAQ,EAAE,CAYhE;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CA2C3D"}
1
+ {"version":3,"file":"renderInputAssets.d.ts","sourceRoot":"","sources":["../src/renderInputAssets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAIzD,MAAM,MAAM,SAAS,GACjB,QAAQ,GACR,OAAO,GACP,YAAY,GACZ,OAAO,GACP,cAAc,GACd,MAAM,GACN,YAAY,GACZ,gBAAgB,CAAC;AAErB,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,SAAS,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,CAM/C;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,IAAI,MAAM,GAAG,SAAS,CAAC;IAC1B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAkHD,wBAAiB,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,SAAS,CAAC,SAAS,CAAC,CAoDpE;AAsBD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,QAAQ,EAAE,CAYhE;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CA2C3D"}
package/dist/authoring.js CHANGED
@@ -48,7 +48,7 @@ import {
48
48
  formatPlanSteps,
49
49
  initCodeGenPrompts
50
50
  } from "./chunk-Y4HPN4BC.js";
51
- import "./chunk-Q244EHRI.js";
51
+ import "./chunk-GMVUJYPM.js";
52
52
  import {
53
53
  cssLayoutVars
54
54
  } from "./chunk-W5W3FDDI.js";
@@ -62,7 +62,7 @@ import "./chunk-WPZKOVYF.js";
62
62
  import "./chunk-B7J5UUUV.js";
63
63
  import "./chunk-KYRDKK2D.js";
64
64
  import "./chunk-WREYUH2E.js";
65
- import "./chunk-WYKUWRQG.js";
65
+ import "./chunk-A3MXR6JI.js";
66
66
  import "./chunk-7PA7FGLD.js";
67
67
  import {
68
68
  collectSceneClipIssues,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  CueframeError,
3
3
  encodeError
4
- } from "./chunk-WYKUWRQG.js";
4
+ } from "./chunk-A3MXR6JI.js";
5
5
 
6
6
  // ../execution/core/src/render/vcam/constants.ts
7
7
  var P_MIN = 0.5;
@@ -1,6 +1,10 @@
1
+ import {
2
+ cssUrlPayloads,
3
+ isFragmentReference
4
+ } from "./chunk-OSMXQV5V.js";
1
5
  import {
2
6
  CueframeError
3
- } from "./chunk-WYKUWRQG.js";
7
+ } from "./chunk-A3MXR6JI.js";
4
8
 
5
9
  // ../execution/render-harness/src/cardAssetAdmission.ts
6
10
  import parseCss from "css-tree/parser";
@@ -41,9 +45,6 @@ var CSS_VALUE_ATTRIBUTES = /* @__PURE__ */ new Set([
41
45
  "mask",
42
46
  "stroke"
43
47
  ]);
44
- function isFragmentReference(value) {
45
- return value.trim().startsWith("#");
46
- }
47
48
  function refuse(locator, reason) {
48
49
  throw new CueframeError(
49
50
  "card_external_asset_forbidden",
@@ -84,8 +85,8 @@ function assertNodeAssetFree(node, locator) {
84
85
  }
85
86
  if (name === "style") assertCssAssetFree(attr.value, "declarationList", locator);
86
87
  if (CSS_VALUE_ATTRIBUTES.has(name)) {
87
- for (const match of attr.value.matchAll(/url\(\s*(['"]?)(.*?)\1\s*\)/gi)) {
88
- if (!isFragmentReference(match[2] ?? "")) {
88
+ for (const payload of cssUrlPayloads(attr.value)) {
89
+ if (!isFragmentReference(payload)) {
89
90
  refuse(locator, `contains an unmanifested ${name} url() asset reference`);
90
91
  }
91
92
  }
@@ -312,7 +312,7 @@ Call wait_job(kind="compose", id="${j.composeJobId}", projectId="${a.projectId}"
312
312
  name: "apply_composition",
313
313
  operationId: "applyComposition",
314
314
  pathArgs: { projectId: "id" },
315
- description: 'Atomically apply an array of CompositionOps to a project composition. All ops succeed or none do (transactional). Pass `if_match` for optimistic-concurrency control (409 stale_etag on mismatch) and `dry_run: true` to validate the batch without persisting. Use this to seed a composition (add media clips) or make targeted edits (set a crop intent, reorder clips, set the format). CAPTIONS: attach content with {type:"captions.fromTranscript", mediaId, window?} \u2014 the server slices the cached word-timed transcript, rebases times, and sentence-splits into segments (no pasting words; 422 media_no_transcript if the media has no speech); style it with {type:"setCaptionStyle", style}; or set explicit words with {type:"setCaptions", segments, style?} (e.g. translations or your own VO timings). Brand is NOT set here \u2014 it lives on the project (create_project / update_project with brandKitId \u2014 or PATCH /projects/:id over REST). CARDS: a {kind:"card", html, tokens} clip projects each `tokens` KEY `x` to the CSS custom property `--cf-x`, so the html must read it as `var(--cf-x)` \u2014 write `tokens:{"plate":"#0af"}` + `background:var(--cf-plate)`. Do NOT put dashes in the key: `"--plate"` becomes `--cf---plate` and your `var(--plate)` then resolves to NOTHING, which CSS silently degrades to a transparent background and black text. Responses carry `warnings[]` when a card reads a var nothing defines. SCENE SHOTS: for a 3D product shot \u2014 a tilted page screenshot, a lit laptop/phone showing a real screenshot, two-colour type, a colour-field backdrop, focus/grain/vignette and a camera move \u2014 use {type:"scene.add", clipId, newTrack|trackId, startTime, duration, scene, assets} and revise it with {type:"scene.update", clipId, scene?, assets?, startTime?, duration?}. You author a scene SPEC, never wrapper TSX; the server registers the component for you. There is NO built-in scene primitive in list_catalog \u2014 READ cueframe://scene-shot first for the JSON schema, the canonical V2 world-objects recipe with nested groups, slabs, pages, phones, laptops, world/screen text, admitted surfaces, camera motion, lighting, and the current resource limits.',
315
+ description: 'Atomically apply an array of CompositionOps to a project composition. All ops succeed or none do (transactional). Pass `if_match` for optimistic-concurrency control (409 stale_etag on mismatch) and `dry_run: true` to validate the batch without persisting. Ops land on the project\'s ACTIVE composition unless you pass `composition_id` (mutually exclusive with `session_id`), which targets a specific one \u2014 that is how you author a second composition minted with new_composition and run an A/B. Use this to seed a composition (add media clips) or make targeted edits (set a crop intent, reorder clips, set the format). CAPTIONS: attach content with {type:"captions.fromTranscript", mediaId, window?} \u2014 the server slices the cached word-timed transcript, rebases times, and sentence-splits into segments (no pasting words; 422 media_no_transcript if the media has no speech); style it with {type:"setCaptionStyle", style}; or set explicit words with {type:"setCaptions", segments, style?} (e.g. translations or your own VO timings). Brand is NOT set here \u2014 it lives on the project (create_project / update_project with brandKitId \u2014 or PATCH /projects/:id over REST). CARDS: a {kind:"card", html, tokens} clip projects each `tokens` KEY `x` to the CSS custom property `--cf-x`, so the html must read it as `var(--cf-x)` \u2014 write `tokens:{"plate":"#0af"}` + `background:var(--cf-plate)`. Do NOT put dashes in the key: `"--plate"` becomes `--cf---plate` and your `var(--plate)` then resolves to NOTHING, which CSS silently degrades to a transparent background and black text. Responses carry `warnings[]` when a card reads a var nothing defines. SCENE SHOTS: for a 3D product shot \u2014 a tilted page screenshot, a lit laptop/phone showing a real screenshot, two-colour type, a colour-field backdrop, focus/grain/vignette and a camera move \u2014 use {type:"scene.add", clipId, newTrack|trackId, startTime, duration, scene, assets} and revise it with {type:"scene.update", clipId, scene?, assets?, startTime?, duration?}. You author a scene SPEC, never wrapper TSX; the server registers the component for you. There is NO built-in scene primitive in list_catalog \u2014 READ cueframe://scene-shot first for the JSON schema, the canonical V2 world-objects recipe with nested groups, slabs, pages, phones, laptops, world/screen text, admitted surfaces, camera motion, lighting, and the current resource limits.',
316
316
  okFormat: (j, a) => {
317
317
  const warns = formatWarnings(j);
318
318
  if (j && typeof j.valid === "boolean") {
@@ -569,7 +569,7 @@ etag: ${j.etag}`
569
569
  name: "get_composition",
570
570
  operationId: "getComposition",
571
571
  pathArgs: { projectId: "id" },
572
- description: "READ BACK the project's active composition as JSON \u2014 the edit itself: tracks, clips, card HTML, reframe segments, captions, markers, format. This is what create_render encodes, so it is also what you hand to validate_composition (which needs a full inline composition body), what you diff after an edit, and what you archive/share so someone else can re-render the SAME video. Read-only and free. Authoring stays op-based (apply_composition) \u2014 do not round-trip this object back as a write. A composition too large to fit one MCP result degrades to a STRUCTURAL SUMMARY (every track and clip still listed; card html and caption words elided as lengths) with a header saying so \u2014 read it over REST if you need the verbatim body.",
572
+ description: "READ BACK a composition as JSON \u2014 the edit itself: tracks, clips, card HTML, reframe segments, captions, markers, format. This is what create_render encodes, so it is also what you hand to validate_composition (which needs a full inline composition body), what you diff after an edit, and what you archive/share so someone else can re-render the SAME video. Read-only and free. Authoring stays op-based (apply_composition) \u2014 do not round-trip this object back as a write. A composition too large to fit one MCP result degrades to a STRUCTURAL SUMMARY (every track and clip still listed; card html and caption words elided as lengths) with a header saying so \u2014 read it over REST if you need the verbatim body. Defaults to the project's ACTIVE composition; pass `compositionId` to read a specific one (the same id apply_composition takes as `composition_id`, and preview_frame / create_render take as compositionId) so an A/B variant can be read back, not just written.",
573
573
  okFormat: (j) => formatComposition(j),
574
574
  annotations: { readOnlyHint: true }
575
575
  },
@@ -440,6 +440,34 @@ function scrubAll(obj) {
440
440
  for (const [k, v] of Object.entries(obj)) out[k] = scrubVal(v);
441
441
  return Object.keys(out).length ? out : void 0;
442
442
  }
443
+ var DEFAULT_RETRY_AFTER_SECONDS = 30;
444
+ var BUSY_RETRY_AFTER_SECONDS = 5;
445
+ var PROVIDER_RETRY_AFTER_SECONDS = 60;
446
+ var RETRY_AFTER_OVERRIDES = {
447
+ idempotency_conflict: BUSY_RETRY_AFTER_SECONDS,
448
+ resource_import_in_flight: BUSY_RETRY_AFTER_SECONDS,
449
+ capture_busy: BUSY_RETRY_AFTER_SECONDS,
450
+ snapshot_stale: BUSY_RETRY_AFTER_SECONDS,
451
+ too_many_active_sessions: BUSY_RETRY_AFTER_SECONDS,
452
+ rate_limited: PROVIDER_RETRY_AFTER_SECONDS,
453
+ billing_unavailable: PROVIDER_RETRY_AFTER_SECONDS,
454
+ render_provider_unreachable: PROVIDER_RETRY_AFTER_SECONDS,
455
+ render_provider_start_failed: PROVIDER_RETRY_AFTER_SECONDS,
456
+ render_pipeline_unavailable: PROVIDER_RETRY_AFTER_SECONDS,
457
+ sighted_provider_unreachable: PROVIDER_RETRY_AFTER_SECONDS,
458
+ lambda_infra_failed: PROVIDER_RETRY_AFTER_SECONDS,
459
+ pipeline_unavailable: PROVIDER_RETRY_AFTER_SECONDS,
460
+ mux_unavailable: PROVIDER_RETRY_AFTER_SECONDS,
461
+ import_unavailable: PROVIDER_RETRY_AFTER_SECONDS,
462
+ import_source_unreachable: PROVIDER_RETRY_AFTER_SECONDS,
463
+ generator_unavailable: PROVIDER_RETRY_AFTER_SECONDS,
464
+ service_unavailable: PROVIDER_RETRY_AFTER_SECONDS
465
+ };
466
+ function retryAfterSecondsFor(code) {
467
+ const spec = ERROR_CODES[code];
468
+ if (!spec?.retryable) return void 0;
469
+ return spec.retryAfterSeconds ?? RETRY_AFTER_OVERRIDES[code] ?? DEFAULT_RETRY_AFTER_SECONDS;
470
+ }
443
471
  function toWireEnvelope(e, opts) {
444
472
  const trusted = opts?.trusted ?? false;
445
473
  let message;
@@ -455,7 +483,10 @@ function toWireEnvelope(e, opts) {
455
483
  fix = pickScrub(e.fix, FIX_ALLOW);
456
484
  }
457
485
  const locator = pickScrub(e.locator, LOCATOR_ALLOW);
458
- return { ...e, message, fix, locator };
486
+ const thrown = typeof fix?.retryAfter === "number" ? fix.retryAfter : void 0;
487
+ const retryAfter = thrown ?? retryAfterSecondsFor(e.code);
488
+ const withRetry = retryAfter === void 0 ? fix : { ...fix ?? {}, retryAfter };
489
+ return { ...e, message, fix: withRetry, locator };
459
490
  }
460
491
 
461
492
  export {
@@ -464,5 +495,6 @@ export {
464
495
  encodeError,
465
496
  decodeError,
466
497
  scrubSensitive,
498
+ retryAfterSecondsFor,
467
499
  toWireEnvelope
468
500
  };