cueframe 0.8.3 → 0.9.1

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.
@@ -261,4 +261,4 @@ frames) before declaring done.
261
261
  which is the engine's job now.
262
262
  - This recipe lives in a skill on purpose: the engine stays use-case-free; the
263
263
  product opinions (what to extract, which overlays, how to brand) live here and
264
- ship via `npx -y cueframe@0.8 install`.
264
+ ship via `npx -y cueframe@0.9 install`.
@@ -31,11 +31,11 @@ both MCP and this CLI exist so you do not have to.
31
31
 
32
32
  ## Overview
33
33
 
34
- The `cueframe` CLI drives the CueFrame platform from the terminal. Optimized for agents — every command supports `--json` (NDJSON event stream) and the binary self-describes via `npx -y cueframe@0.8 describe --json`.
34
+ The `cueframe` CLI drives the CueFrame platform from the terminal. Optimized for agents — every command supports `--json` (NDJSON event stream) and the binary self-describes via `npx -y cueframe@0.9 describe --json`.
35
35
 
36
- **Run it as `npx -y cueframe@0.8 …` — every command in this skill is written that way, and
36
+ **Run it as `npx -y cueframe@0.9 …` — every command in this skill is written that way, and
37
37
  that form is executable verbatim.** There is no `cueframe` on your PATH unless you put it
38
- there: `npx -y cueframe@0.8 install` wires the MCP server and drops these skills, but npx
38
+ there: `npx -y cueframe@0.9 install` wires the MCP server and drops these skills, but npx
39
39
  unpacks to an ephemeral cache, so it installs no binary. `npx` re-resolves the current
40
40
  version on each call (~0.5s warm, ~5s cold), which also means these commands never go
41
41
  stale. If you are running many in a row and want to skip that, `npm i -g cueframe` once
@@ -46,9 +46,9 @@ the documented path.
46
46
  **The framework is three verbs:** `upload` (register media) → `composition put` (author the timeline) → `render` (→ MP4). The `Composition` is the contract — render takes the saved composition, nothing else. Everything domain-specific (AI clip suggestions, FCPXML/Premiere export) is a **use-case on-ramp** layered on top, not part of the core.
47
47
 
48
48
  **Core principle — discover, don't guess.** Never author a composition from the
49
- examples below alone. The live contract is `npx -y cueframe@0.8 schema composition` (prints
49
+ examples below alone. The live contract is `npx -y cueframe@0.9 schema composition` (prints
50
50
  the real wire schema the server enforces); confirm any draft with
51
- `npx -y cueframe@0.8 composition validate -b @file.json` BEFORE you render. Validation is
51
+ `npx -y cueframe@0.9 composition validate -b @file.json` BEFORE you render. Validation is
52
52
  free and instant; a render is neither. The examples here are orientation — the
53
53
  schema is the source of truth.
54
54
 
@@ -70,20 +70,20 @@ delivery, not checking each edit. CLI validation does not replace visual evidenc
70
70
  # Commands run against production; auth is stored in ~/.cueframe/auth.json.
71
71
 
72
72
  # 1. Register media (one or many — mixed video / image / audio).
73
- npx -y cueframe@0.8 upload "/path/to/source.mp4" --json # → mediaItemId (process_complete)
73
+ npx -y cueframe@0.9 upload "/path/to/source.mp4" --json # → mediaItemId (process_complete)
74
74
 
75
75
  # 2. Create a project (sets aspect/format).
76
- npx -y cueframe@0.8 project create -n "promo" -a 9:16 --json # → projectId
76
+ npx -y cueframe@0.9 project create -n "promo" -a 9:16 --json # → projectId
77
77
 
78
78
  # 3. Author the composition: tracks of clips (per-clip reframe/trim), optional
79
79
  # captions (captions.segments), brandKitId. The composition is the SSOT.
80
80
  # Discover the live schema, then validate the draft BEFORE saving/rendering:
81
- npx -y cueframe@0.8 schema composition # → live wire schema
82
- npx -y cueframe@0.8 composition validate -b @composition.json # → ✓ valid | per-field errors (no render)
83
- npx -y cueframe@0.8 composition put <projectId> -b @composition.json # ETag auto
81
+ npx -y cueframe@0.9 schema composition # → live wire schema
82
+ npx -y cueframe@0.9 composition validate -b @composition.json # → ✓ valid | per-field errors (no render)
83
+ npx -y cueframe@0.9 composition put <projectId> -b @composition.json # ETag auto
84
84
 
85
85
  # 4. Render the saved composition to MP4. SSE-watches + downloads when done.
86
- npx -y cueframe@0.8 render <projectId> -o ./out.mp4 --json
86
+ npx -y cueframe@0.9 render <projectId> -o ./out.mp4 --json
87
87
  # → render_queued → render_progress* → render_complete
88
88
  #
89
89
  # `render` takes ONLY a projectId and renders the SAVED composition (tracks +
@@ -92,14 +92,14 @@ npx -y cueframe@0.8 render <projectId> -o ./out.mp4 --json
92
92
  # a hand-authored composition; if absent, the clip is rendered without captions.
93
93
 
94
94
  # Reattach to an in-flight render later (e.g. after disconnect):
95
- npx -y cueframe@0.8 render watch <renderId> -p <projectId> -o ./out.mp4 --json
95
+ npx -y cueframe@0.9 render watch <renderId> -p <projectId> -o ./out.mp4 --json
96
96
  ```
97
97
 
98
98
  ## Anatomy of a composition.json
99
99
 
100
100
  This section orients you to the shape; the authoritative contract is
101
- `npx -y cueframe@0.8 schema composition` (the live wire schema) — run it when a field is
102
- unclear, and `npx -y cueframe@0.8 composition validate -b @file.json` to check a draft.
101
+ `npx -y cueframe@0.9 schema composition` (the live wire schema) — run it when a field is
102
+ unclear, and `npx -y cueframe@0.9 composition validate -b @file.json` to check a draft.
103
103
 
104
104
  `composition put` takes the **bare** `Composition` object (no wrapper; the CLI POSTs
105
105
  the `@file` verbatim and handles the ETag). Minimal valid shape:
@@ -166,18 +166,18 @@ the composition yourself (above).
166
166
 
167
167
  ```bash
168
168
  # 1. Upload + chain the AI clip pass.
169
- npx -y cueframe@0.8 upload "/path/to/source.mp4" --analyze --json # mediaItemId + suggestions
170
- # (or run it explicitly: npx -y cueframe@0.8 analyze <mediaItemId> --wait --json)
169
+ npx -y cueframe@0.9 upload "/path/to/source.mp4" --analyze --json # mediaItemId + suggestions
170
+ # (or run it explicitly: npx -y cueframe@0.9 analyze <mediaItemId> --wait --json)
171
171
 
172
172
  # 2. List clip suggestions (publicId sug_…, title, startMs/endMs, score).
173
- npx -y cueframe@0.8 clips <mediaItemId> --json
173
+ npx -y cueframe@0.9 clips <mediaItemId> --json
174
174
 
175
175
  # 3. Create a project AND author its composition from the chosen suggestion.
176
- npx -y cueframe@0.8 project create -n "paul-klein-shorts" -a 9:16 --from-suggestion <sug_…> --json
177
- # (or, on an existing project: npx -y cueframe@0.8 composition from-suggestion <projectId> -s <sug_…>)
176
+ npx -y cueframe@0.9 project create -n "paul-klein-shorts" -a 9:16 --from-suggestion <sug_…> --json
177
+ # (or, on an existing project: npx -y cueframe@0.9 composition from-suggestion <projectId> -s <sug_…>)
178
178
 
179
179
  # 4. Render — same framework verb as above.
180
- npx -y cueframe@0.8 render <projectId> -o ./out.mp4 --json
180
+ npx -y cueframe@0.9 render <projectId> -o ./out.mp4 --json
181
181
  ```
182
182
 
183
183
  Both flows converge on `composition put` → `render`; the on-ramp just authors the
@@ -194,10 +194,10 @@ video and composites it (the shared renderer never runs your code).
194
194
 
195
195
  ```bash
196
196
  # 1. Scaffold a workspace (writes cueframe.json + cueframe/components/). Idempotent.
197
- npx -y cueframe@0.8 init --json
197
+ npx -y cueframe@0.9 init --json
198
198
 
199
199
  # 2a. Scaffold a component in cueframe/components/<id>/ as owned, editable source.
200
- npx -y cueframe@0.8 new component my-badge --json
200
+ npx -y cueframe@0.9 new component my-badge --category ui-blocks --json
201
201
 
202
202
  # The scaffold is a native (version 4) source: template.html + definition.json, with its
203
203
  # manifest in cueframe.json. Built-in forks copy the exact template, definition and manifest.
@@ -206,38 +206,38 @@ npx -y cueframe@0.8 new component my-badge --json
206
206
  # __cfScene.mount(...)) and definition.json (inputs, defaults, timing, capabilities).
207
207
 
208
208
  # 4. Publish to CueFrame so it can render (the server admits the source or names the rule it breaks).
209
- npx -y cueframe@0.8 push my-badge --json # one component
210
- npx -y cueframe@0.8 sync --json # every component in the workspace
209
+ npx -y cueframe@0.9 push my-badge --json # one component
210
+ npx -y cueframe@0.9 sync --json # every component in the workspace
211
211
 
212
212
  # 5. Reference the component id in your composition as a {kind:'component', componentId, props}
213
213
  # clip, then render with the same verb. Preview a single component first via the MCP
214
214
  # preview_component loop.
215
- npx -y cueframe@0.8 render <projectId> -o ./out.mp4 --json
215
+ npx -y cueframe@0.9 render <projectId> -o ./out.mp4 --json
216
216
  ```
217
217
 
218
218
  ## Quick reference
219
219
 
220
220
  | Need to… | Command |
221
221
  |---|---|
222
- | See every command + flags | `npx -y cueframe@0.8 describe --json` |
223
- | Install/refresh managed skills | `npx -y cueframe@0.8 install` (shared `~/.agents/skills` and Claude `~/.claude/skills`; locally changed or untracked packages are preserved and reported) |
224
- | List projects | `npx -y cueframe@0.8 list -n 50` |
225
- | List your media | `npx -y cueframe@0.8 clips` (no mediaId arg) |
226
- | Discover the live composition schema | `npx -y cueframe@0.8 schema composition` |
227
- | Validate a draft (no save, no render) | `npx -y cueframe@0.8 composition validate -b @plan.json` |
228
- | Read composition + ETag | `npx -y cueframe@0.8 composition get <projectId> --json` |
229
- | Write composition | `npx -y cueframe@0.8 composition put <projectId> -b @plan.json` (ETag auto) |
230
- | Export to Final Cut | `npx -y cueframe@0.8 export fcpxml <projectId> -s <sug> --wait -o cut.zip` |
231
- | Export to Premiere | `npx -y cueframe@0.8 export premiere <projectId> -s <sug> --wait -o cut.zip` |
232
- | Anything not wrapped | `npx -y cueframe@0.8 api GET /v1/... -i` (escape hatch, like `gh api`) |
233
- | Validate a composition without mutating | `npx -y cueframe@0.8 composition validate -b @plan.json` |
222
+ | See every command + flags | `npx -y cueframe@0.9 describe --json` |
223
+ | Install/refresh managed skills | `npx -y cueframe@0.9 install` (shared `~/.agents/skills` and Claude `~/.claude/skills`; locally changed or untracked packages are preserved and reported) |
224
+ | List projects | `npx -y cueframe@0.9 list -n 50` |
225
+ | List your media | `npx -y cueframe@0.9 clips` (no mediaId arg) |
226
+ | Discover the live composition schema | `npx -y cueframe@0.9 schema composition` |
227
+ | Validate a draft (no save, no render) | `npx -y cueframe@0.9 composition validate -b @plan.json` |
228
+ | Read composition + ETag | `npx -y cueframe@0.9 composition get <projectId> --json` |
229
+ | Write composition | `npx -y cueframe@0.9 composition put <projectId> -b @plan.json` (ETag auto) |
230
+ | Export to Final Cut | `npx -y cueframe@0.9 export fcpxml <projectId> -s <sug> --wait -o cut.zip` |
231
+ | Export to Premiere | `npx -y cueframe@0.9 export premiere <projectId> -s <sug> --wait -o cut.zip` |
232
+ | Anything not wrapped | `npx -y cueframe@0.9 api GET /v1/... -i` (escape hatch, like `gh api`) |
233
+ | Validate a composition without mutating | `npx -y cueframe@0.9 composition validate -b @plan.json` |
234
234
 
235
235
  ## Auth
236
236
 
237
237
  Commands run against production. Authenticate once:
238
238
 
239
- - `npx -y cueframe@0.8 login` — OAuth device flow (laptops).
240
- - `npx -y cueframe@0.8 auth <cf_live_… key>` — save a static API key (CI / headless).
239
+ - `npx -y cueframe@0.9 login` — OAuth device flow (laptops).
240
+ - `npx -y cueframe@0.9 auth <cf_live_… key>` — save a static API key (CI / headless).
241
241
 
242
242
  Creds are stored in `~/.cueframe/auth.json`; the key can also come from the `CUEFRAME_API_KEY` env var.
243
243
 
@@ -255,11 +255,11 @@ Errors come as `{"event":"error", "phase":"<step>", "message":"...", "code":"...
255
255
 
256
256
  | Mistake | Reality |
257
257
  |---|---|
258
- | Reaching for `curl …/v1/...` because the CLI didn't have a command | Use `npx -y cueframe@0.8 api METHOD /v1/...` — same auth, same JSON pipeline. |
259
- | Polling for render completion with a sleep loop | `npx -y cueframe@0.8 render` already SSE-watches and exits when done. Use `render watch <id>` to reattach. |
258
+ | Reaching for `curl …/v1/...` because the CLI didn't have a command | Use `npx -y cueframe@0.9 api METHOD /v1/...` — same auth, same JSON pipeline. |
259
+ | Polling for render completion with a sleep loop | `npx -y cueframe@0.9 render` already SSE-watches and exits when done. Use `render watch <id>` to reattach. |
260
260
  | Skipping `--json` and trying to parse human output | Human output is for humans. Agents always use `--json`. |
261
261
  | Hand-editing the composition without an ETag | `composition put` GETs the ETag for you; `from-suggestion` rebuilds from a clip. Don't hand-craft unless you have to. |
262
- | Calling `npx -y cueframe@0.8 render <projectId> <suggestionId>` (old two-positional shape) | `render` takes ONLY a projectId; commander rejects the extra arg. It renders the SAVED composition — author it first via `composition put` (hand-author) or `project create --from-suggestion <sug>` (clip-finder on-ramp). |
262
+ | Calling `npx -y cueframe@0.9 render <projectId> <suggestionId>` (old two-positional shape) | `render` takes ONLY a projectId; commander rejects the extra arg. It renders the SAVED composition — author it first via `composition put` (hand-author) or `project create --from-suggestion <sug>` (clip-finder on-ramp). |
263
263
  | Assuming `render` needs a clip suggestion / that captions only come from a suggestion | No — `render` renders the saved composition directly; a suggestion is optional. Captions come from `composition.captions` (author them in the `put` JSON). The clip-suggestion on-ramp just fills those captions for you by slicing the transcript at author time. |
264
264
 
265
265
  ## When this skill applies (routing)
@@ -80,18 +80,19 @@ Source lives in `cueframe/components/<id>/` (the `cueframe.json` workspace); edi
80
80
  template locally, push to render.
81
81
 
82
82
  ```bash
83
- npx -y cueframe@0.8 init --json # scaffold cueframe.json + cueframe/components/
84
- npx -y cueframe@0.8 new component my-badge --json # scaffold a component in the workspace
83
+ npx -y cueframe@0.9 init --json # scaffold cueframe.json + cueframe/components/
84
+ npx -y cueframe@0.9 new component my-badge --category ui-blocks --json # scaffold a component in the workspace
85
85
  # New scaffolds contain template.html and definition.json (native source, version 4).
86
86
  # …edit cueframe/components/<id>/template.html and definition.json in your editor…
87
- npx -y cueframe@0.8 push my-badge --json # send the native source; the server admits it
88
- # or: npx -y cueframe@0.8 sync --json # push every component in the workspace
87
+ npx -y cueframe@0.9 push my-badge --json # send the native source; the server admits it
88
+ # or: npx -y cueframe@0.9 sync --json # push every component in the workspace
89
89
  # reference the component id in your composition, then render:
90
- npx -y cueframe@0.8 render <projectId> -o ./out.mp4 --json
90
+ npx -y cueframe@0.9 render <projectId> -o ./out.mp4 --json
91
91
  ```
92
92
 
93
93
  The CLI writes `template.html` and `definition.json` (input schema, defaults, timing and
94
- capabilities). The version-4 manifest lives at `cueframe.json` → `components.<id>.manifest`.
94
+ capabilities). `cueframe.json` → `components.<id>` holds the version-4 `manifest` and the catalog
95
+ `name` and `category`, which `push` requires; it refuses a component missing either.
95
96
  `push`/`sync` send these as one native `source`, checked against the contract's source schema;
96
97
  the server's admission (template lint, determinism, declarations) refuses with a named rule.
97
98
  For a builtin fork, copy **all three parts** from the selected `sourceSnapshot`: template,
@@ -23,7 +23,7 @@ When a required capability is missing, explain the limitation and the supported
23
23
  - **Claude.ai / Claude Desktop:** Settings → Connectors → add a custom connector with
24
24
  `https://api.cueframe.ai/v1/mcp`.
25
25
  - **Other agents (Cursor, Codex, VS Code, Windsurf, Zed, Antigravity CLI, Copilot CLI, …):**
26
- use `npx -y cueframe@0.8 install --help` to select the intended client; preserve existing configuration and avoid duplicate installs.
26
+ use `npx -y cueframe@0.9 install --help` to select the intended client; preserve existing configuration and avoid duplicate installs.
27
27
  - **ChatGPT:** the CLI cannot wire it because there is no local config to write; add
28
28
  `https://api.cueframe.ai/v1/mcp` as a custom connector instead.
29
29
  - **No account (pay per call):** connect
@@ -21,7 +21,7 @@ to author, not how to transport it.
21
21
 
22
22
  **Drive the primitives over MCP if you can call tools** (`new_composition` /
23
23
  `apply_composition` / `validate_composition` / `create_render` — see the
24
- `cueframe-connect` skill for the one-line setup). The `npx -y cueframe@0.8 …` commands
24
+ `cueframe-connect` skill for the one-line setup). The `npx -y cueframe@0.9 …` commands
25
25
  written out below are the same operations for a terminal or CI job with no MCP
26
26
  host; see the `cueframe-cli` skill.
27
27
 
@@ -64,7 +64,7 @@ style's) over each window. Result → `source.reframe.segments` on the clip.
64
64
  ## 3. Compose
65
65
 
66
66
  One video track, the screen recording as a media clip carrying the reframe.
67
- `npx -y cueframe@0.8 composition put <projectId> -b @composition.json` (see `cueframe-cli`).
67
+ `npx -y cueframe@0.9 composition put <projectId> -b @composition.json` (see `cueframe-cli`).
68
68
  Choose `-a 16:9` for landscape product video, `9:16` for social.
69
69
 
70
70
  ## 4. Polish — layer overlay primitives (this is what makes it look "produced")
@@ -101,21 +101,21 @@ check framing with `preview_frame` and click/zoom timing with an affected-window
101
101
  For a small revision, verify that change and relevant regressions without exporting the whole film.
102
102
  When delivering the finished video:
103
103
 
104
- `npx -y cueframe@0.8 render <projectId> -o out.mp4 --json`. Verify the output (ffprobe +
104
+ `npx -y cueframe@0.9 render <projectId> -o out.mp4 --json`. Verify the output (ffprobe +
105
105
  sample frames) before declaring done.
106
106
 
107
107
  ## Worked examples — composition JSON
108
108
 
109
109
  These are **orientation, not the contract.** The live wire schema is
110
- `npx -y cueframe@0.8 schema composition`, and the way to know a draft is correct is
111
- `npx -y cueframe@0.8 composition validate -b @composition.json` — it runs the same
110
+ `npx -y cueframe@0.9 schema composition`, and the way to know a draft is correct is
111
+ `npx -y cueframe@0.9 composition validate -b @composition.json` — it runs the same
112
112
  validator the server enforces, with no save and no render. Discover + validate
113
113
  before you render; never spend a render to find a schema mistake.
114
114
 
115
115
  Each block below is a complete `@composition.json` (the bare object `composition put`
116
116
  accepts: top-level `v`, `format`, `tracks`, optional `captions`). All five validate
117
117
  against the real wire schema + save invariants (swap the `<…MediaId>` placeholders for
118
- real `npx -y cueframe@0.8 upload` ids). Conventions that keep them valid:
118
+ real `npx -y cueframe@0.9 upload` ids). Conventions that keep them valid:
119
119
 
120
120
  - Tracks hold **`contents`** (not `clips`); each clip wraps a `source`.
121
121
  - A clip's `source.kind` must match the track `kind`: `media` → `video`/`image`/`audio`
@@ -297,4 +297,4 @@ Talking-head with an `active-speaker` reframe and a `heroText` title at `zPlane:
297
297
  background. See EX3 / EX4 below.
298
298
  - This recipe lives in a skill on purpose: the engine stays use-case-free; the
299
299
  product opinions (style, which primitives, layout) live here and ship via
300
- `npx -y cueframe@0.8 install`. Add sibling recipes (`cueframe-podcast-clip`, …) the same way.
300
+ `npx -y cueframe@0.9 install`. Add sibling recipes (`cueframe-podcast-clip`, …) the same way.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cueframe",
3
- "version": "0.8.3",
3
+ "version": "0.9.1",
4
4
  "description": "CueFrame video editing CLI: manage media, edit compositions and render MP4s from terminals and scripts.",
5
5
  "keywords": [
6
6
  "cueframe",
@@ -37,16 +37,16 @@
37
37
  "commander": "^13.1.0",
38
38
  "open": "^10.1.0",
39
39
  "ora": "^8.2.0",
40
- "pino": "^10.3.1",
41
- "typescript": "^5.9.3"
40
+ "pino": "^10.3.1"
42
41
  },
43
42
  "devDependencies": {
44
43
  "zod": "^4.5.4",
45
44
  "@types/node": "^24.0.0",
46
45
  "tsup": "^8.5.1",
46
+ "typescript": "^5.9.3",
47
47
  "vitest": "^4.1.2",
48
- "@cueframe/sdk": "^0.7.1",
49
- "@cueframe/skills": "0.3.0"
48
+ "@cueframe/skills": "0.3.2",
49
+ "@cueframe/sdk": "^0.9.0"
50
50
  },
51
51
  "repository": {
52
52
  "type": "git",
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- import{F as a}from"./chunk-C4HCB4HG.js";import"./chunk-3QSA3EBY.js";export{a as analyzeCommand};
@@ -1,12 +0,0 @@
1
- #!/usr/bin/env node
2
- import{a as y}from"./chunk-3QSA3EBY.js";var u=class extends Error{status;code;details;requestId;constructor(t,r,n){super(r.message),this.name="ApiError",this.status=t,this.code=r.code,this.details=r.details,this.requestId=n}},v=class extends Error{url;timeoutMs;constructor(t,r){super(`Request timed out after ${r}ms: ${t}`),this.name="TimeoutError",this.url=t,this.timeoutMs=r}},q=class extends Error{url;constructor(t,r){super(`Request failed before a response: ${t}`,{cause:r}),this.name="NetworkError",this.url=t}},g={baseUrl:""};function I(e){return g={timeoutMs:3e4,...e},g}function j(){return g}function tt(e,t){return/^https?:\/\//.test(t)?t:e.replace(/\/$/,"")+(t.startsWith("/")?t:`/${t}`)}async function L(e,t={}){if(!g.baseUrl)throw new Error("@cueframe/sdk: createClient({baseUrl}) must be called before issuing requests.");let r=g.fetch??fetch,n=tt(g.baseUrl,e),o=new Headers({accept:"application/json"});for(let[c,f]of Object.entries(g.headers??{}))o.set(c,f);t.headers&&new Headers(t.headers).forEach((c,f)=>o.set(f,c)),g.apiKey&&!o.has("authorization")&&o.set("authorization",`Bearer ${g.apiKey}`);let s=g.timeoutMs??3e4,i=new AbortController,p=setTimeout(()=>i.abort(),s),d=t.signal?AbortSignal.any([t.signal,i.signal]):i.signal;try{let c=await r(n,{...t,headers:o,signal:d}),f={};c.headers.forEach((b,x)=>{f[x.toLowerCase()]=b});let l=null;if(c.status!==204)if((c.headers.get("content-type")??"").includes("application/json"))try{l=await c.json()}catch{l=null}else l=await c.text();return{status:c.status,statusText:c.statusText,headers:f,body:l,requestId:f["x-request-id"]}}catch(c){throw t.signal?.aborted?c:i.signal.aborted?new v(n,s):new q(n,c)}finally{clearTimeout(p)}}async function a(e,t={}){let r=await L(e,t);if(r.status>=400){let n;throw r.body&&typeof r.body=="object"&&"error"in r.body?n=r.body.error??{code:"unknown",message:r.statusText}:n={code:"unknown",message:r.statusText},new u(r.status,n,r.requestId)}if(r.status!==204)return r.body}var rt={unauthorized:"The credential is invalid or expired for this target, or it belongs to a different environment. Re-authenticate the way you connected: reconnect the MCP server, run `cueframe login` in a terminal, or supply a current API key.",forbidden:"The credential's permissions don't cover this operation. The server message above names the exact missing ones and the `permissions` body that grants them; a key's permissions are fixed at creation, so this needs a NEW key, not a change to this one.",not_found:"No such resource in this org (cross-org access also reads as 404). Check the id, or enumerate with the matching list command/tool.",media_not_ready:"Media is still processing. Wait for the `media.transcribed` webhook or retry after ~30s.",suggestions_already_complete:"Suggestions already exist for this media item. To re-run, call DELETE /v1/media/:id/suggestions first to reset state.",precondition_required:"Fetch the resource with GET first to obtain its ETag, then resend the write with `If-Match: <etag>`. `cueframe composition get` returns one for you.",stale_etag:"Resource was modified since your last GET \u2014 `details.currentEtag` is the value to thread next. Re-GET (or run `cueframe composition get`) and rebase your edits before retrying.",conflict:"ETag mismatch \u2014 the resource was modified since your last GET. Re-fetch and merge before retrying.",media_in_use:"Media is referenced by other resources. See `details.projectIds` and `details.sessionIds` \u2014 remove those references before deleting.",session_in_use:"Session is referenced by a composition. See `details.projectIds` \u2014 remove those references before deleting.",render_not_cancellable:"Render is already in a terminal state (complete / error / cancelled) and cannot be cancelled.",rate_limited:"Rate limit exceeded. Back off using the `retry-after` response header.",invalid_composition:"Composition violates an invariant (see `details`). Common ones: clip_source_track_kind_mismatch, track_clips_overlap, transition_no_predecessor.",clip_not_found:"The clip suggestion publicId doesn't exist in this org. Run `cueframe clips <mediaItemId>` to enumerate valid sug_* ids.",service_unavailable:"The processing pipeline is temporarily unavailable. Retry shortly; if it persists, contact support@cueframe.ai with the requestId.",payment_required:"The request exceeds a billing limit. For generation, the estimated cost is over the per-call ceiling (see `details.estimateUsd` / `details.ceilingUsd`) \u2014 lower the requested duration or raise the ceiling."};function O(e){return e instanceof u?rt[e.code]??null:null}async function*ot(e,t,r){let n=j();if(!n?.baseUrl)throw new Error(`@cueframe/sdk: createClient({baseUrl}) must be called before ${t}.`);let o=n.baseUrl.replace(/\/$/,"")+e,s=new Headers({accept:"text/event-stream",...n.headers??{}});n.apiKey&&!s.has("authorization")&&s.set("authorization",`Bearer ${n.apiKey}`);let p=await(n.fetch??fetch)(o,{method:"GET",headers:s,signal:r.signal});if(!p.ok){let l;try{l=(await p.json()).error??{code:"unknown",message:p.statusText}}catch{l={code:"unknown",message:p.statusText}}throw new u(p.status,l,p.headers.get("x-request-id")??void 0)}if(!p.body)throw new Error("SSE response has no body");let d=p.body.getReader(),c=new TextDecoder("utf-8"),f="";try{for(;;){let{value:l,done:b}=await d.read();if(b)break;f+=c.decode(l,{stream:!0});let x=f.indexOf(`
3
-
4
- `);for(;x!==-1;){let et=f.slice(0,x);f=f.slice(x+2);let B=nt(et);B&&(yield B),x=f.indexOf(`
5
-
6
- `)}}}finally{try{d.releaseLock()}catch{}}}function nt(e){if(!e.trim())return null;let t=null,r=[];for(let n of e.split(`
7
- `)){if(!n||n.startsWith(":"))continue;let o=n.indexOf(":");if(o===-1)continue;let s=n.slice(0,o),i=n.slice(o+1).replace(/^ /,"");s==="event"?t=i:s==="data"&&r.push(i)}return!t||r.length===0?null:{event:t,data:r.join(`
8
- `)}}async function*st(e,t,r={}){let n=`/v1/projects/${encodeURIComponent(e)}/renders/${encodeURIComponent(t)}/stream`;for await(let o of ot(n,"iterRenderEvents",r)){let s=it(o);s&&(yield s)}}function it(e){let{event:t,data:r}=e;if(r===null||t!=="progress"&&t!=="complete"&&t!=="error")return null;let n;try{n=JSON.parse(r)}catch{return null}return{event:t,data:n}}var P={};y(P,{composeFromSuggestion:()=>ut,getComposeFromSuggestionUrl:()=>N,getListMediaSuggestionsUrl:()=>G,getResetMediaSuggestionsUrl:()=>$,getSuggestBriefsUrl:()=>F,listMediaSuggestions:()=>lt,resetMediaSuggestions:()=>yt,suggestBriefs:()=>gt});var N=e=>`/v1/projects/${e}/composition/from-suggestion`,ut=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(N(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},G=(e,t)=>{let r=new URLSearchParams;Object.entries(t||{}).forEach(([o,s])=>{s!==void 0&&r.append(o,s===null?"null":String(s))});let n=r.toString();return n.length>0?`/v1/media/${e}/suggestions?${n}`:`/v1/media/${e}/suggestions`},lt=async(e,t,r)=>a(G(e,t),{...r,method:"GET"}),F=e=>`/v1/media/${e}/suggestions`,gt=async(e,t)=>a(F(e),{...t,method:"POST"}),$=e=>`/v1/media/${e}/suggestions`,yt=async(e,t)=>a($(e),{...t,method:"DELETE"});var Y={};y(Y,{createComponent:()=>bt,getComponent:()=>ht,getComponentSource:()=>vt,getCreateComponentUrl:()=>D,getGetComponentSourceUrl:()=>X,getGetComponentUrl:()=>z,getListCatalogUrl:()=>H,getPatchComponentUrl:()=>V,getRepinComponentUrl:()=>J,getResolveBuiltinComponentUrl:()=>_,getUpdateComponentUrl:()=>W,listCatalog:()=>Ct,patchComponent:()=>St,repinComponent:()=>xt,resolveBuiltinComponent:()=>Rt,updateComponent:()=>Pt});var J=e=>`/v1/projects/${e}/components/native-upgrade`,xt=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(J(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},_=e=>{let t=new URLSearchParams;Object.entries(e||{}).forEach(([n,o])=>{o!==void 0&&t.append(n,o===null?"null":String(o))});let r=t.toString();return r.length>0?`/v1/components/builtin/resolve?${r}`:"/v1/components/builtin/resolve"},Rt=async(e,t)=>a(_(e),{...t,method:"GET"}),H=e=>{let t=new URLSearchParams;Object.entries(e||{}).forEach(([n,o])=>{o!==void 0&&t.append(n,o===null?"null":String(o))});let r=t.toString();return r.length>0?`/v1/components?${r}`:"/v1/components"},Ct=async(e,t)=>a(H(e),{...t,method:"GET"}),D=()=>"/v1/components",bt=async(e,t)=>{let r=n=>{if(!n)return{};if(n instanceof Headers)return Object.fromEntries(n.entries());if(Symbol.iterator in n)return Object.fromEntries(Array.from(n,s=>Array.from(s)));let o={};for(let[s,i]of Object.entries(n))i!==void 0&&(o[s]=i);return o};return a(D(),{...t,method:"POST",headers:{"Content-Type":"application/json",...r(t?.headers)},body:JSON.stringify(e)})},W=e=>`/v1/components/${e}`,Pt=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(W(e),{...r,method:"PUT",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},V=e=>`/v1/components/${e}`,St=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(V(e),{...r,method:"PATCH",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},z=e=>`/v1/components/${e}`,ht=async(e,t)=>a(z(e),{...t,method:"GET"}),X=(e,t)=>{let r=new URLSearchParams;Object.entries(t||{}).forEach(([o,s])=>{s!==void 0&&r.append(o,s===null?"null":String(s))});let n=r.toString();return n.length>0?`/v1/components/${e}/source?${n}`:`/v1/components/${e}/source`},vt=async(e,t,r)=>a(X(e,t),{...r,method:"GET"});var re={};y(re,{cancelExport:()=>Mt,createFcpxmlExport:()=>Ot,createPremiereExport:()=>wt,getCancelExportUrl:()=>te,getCreateFcpxmlExportUrl:()=>Z,getCreatePremiereExportUrl:()=>Q,getExport:()=>At,getGetExportUrl:()=>ee});var Z=e=>`/v1/projects/${e}/exports/fcpxml`,Ot=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(Z(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},Q=e=>`/v1/projects/${e}/exports/premiere`,wt=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(Q(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},ee=(e,t)=>`/v1/projects/${e}/exports/${t}`,At=async(e,t,r)=>a(ee(e,t),{...r,method:"GET"}),te=(e,t)=>`/v1/projects/${e}/exports/${t}/cancel`,Mt=async(e,t,r)=>a(te(e,t),{...r,method:"POST"});var be={};y(be,{analyzeTimeline:()=>er,analyzeTranscript:()=>Qt,createMediaUpload:()=>Gt,createUploadToken:()=>Nt,deleteMedia:()=>Ht,finalizeMedia:()=>$t,generateMedia:()=>Jt,getAnalyzeTimelineUrl:()=>Ce,getAnalyzeTranscriptUrl:()=>Re,getCreateMediaUploadUrl:()=>se,getCreateUploadTokenUrl:()=>ne,getDeleteMediaUrl:()=>fe,getFinalizeMediaUrl:()=>ae,getGenerateMediaUrl:()=>pe,getGetMediaContextUrl:()=>ue,getGetMediaTranscriptUrl:()=>de,getGetMediaUrl:()=>me,getImportMediaUrl:()=>ce,getListMediaFactsUrl:()=>ye,getListMediaUrl:()=>ie,getMedia:()=>Dt,getMediaContext:()=>Vt,getMediaTranscript:()=>Wt,getPurchaseMediaFactUrl:()=>xe,getSearchLibraryUrl:()=>oe,getTriggerMatteBakeUrl:()=>ge,getTriggerSubjectDetectionUrl:()=>le,importMedia:()=>_t,listMedia:()=>Ft,listMediaFacts:()=>Yt,purchaseMediaFact:()=>Zt,searchLibrary:()=>Lt,triggerMatteBake:()=>Xt,triggerSubjectDetection:()=>zt});var oe=e=>{let t=new URLSearchParams;Object.entries(e||{}).forEach(([n,o])=>{o!==void 0&&t.append(n,o===null?"null":String(o))});let r=t.toString();return r.length>0?`/v1/media/search?${r}`:"/v1/media/search"},Lt=async(e,t)=>a(oe(e),{...t,method:"GET"}),ne=()=>"/v1/uploads/token",Nt=async(e,t)=>{let r=n=>{if(!n)return{};if(n instanceof Headers)return Object.fromEntries(n.entries());if(Symbol.iterator in n)return Object.fromEntries(Array.from(n,s=>Array.from(s)));let o={};for(let[s,i]of Object.entries(n))i!==void 0&&(o[s]=i);return o};return a(ne(),{...t,method:"POST",headers:{"Content-Type":"application/json",...r(t?.headers)},body:JSON.stringify(e)})},se=()=>"/v1/media",Gt=async(e,t)=>{let r=n=>{if(!n)return{};if(n instanceof Headers)return Object.fromEntries(n.entries());if(Symbol.iterator in n)return Object.fromEntries(Array.from(n,s=>Array.from(s)));let o={};for(let[s,i]of Object.entries(n))i!==void 0&&(o[s]=i);return o};return a(se(),{...t,method:"POST",headers:{"Content-Type":"application/json",...r(t?.headers)},body:JSON.stringify(e)})},ie=e=>{let t=new URLSearchParams;Object.entries(e||{}).forEach(([n,o])=>{o!==void 0&&t.append(n,o===null?"null":String(o))});let r=t.toString();return r.length>0?`/v1/media?${r}`:"/v1/media"},Ft=async(e,t)=>a(ie(e),{...t,method:"GET"}),ae=e=>`/v1/media/${e}/finalize`,$t=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(ae(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},pe=()=>"/v1/media/generate",Jt=async(e,t)=>{let r=n=>{if(!n)return{};if(n instanceof Headers)return Object.fromEntries(n.entries());if(Symbol.iterator in n)return Object.fromEntries(Array.from(n,s=>Array.from(s)));let o={};for(let[s,i]of Object.entries(n))i!==void 0&&(o[s]=i);return o};return a(pe(),{...t,method:"POST",headers:{"Content-Type":"application/json",...r(t?.headers)},body:JSON.stringify(e)})},ce=()=>"/v1/media/import",_t=async(e,t)=>{let r=n=>{if(!n)return{};if(n instanceof Headers)return Object.fromEntries(n.entries());if(Symbol.iterator in n)return Object.fromEntries(Array.from(n,s=>Array.from(s)));let o={};for(let[s,i]of Object.entries(n))i!==void 0&&(o[s]=i);return o};return a(ce(),{...t,method:"POST",headers:{"Content-Type":"application/json",...r(t?.headers)},body:JSON.stringify(e)})},fe=e=>`/v1/media/${e}`,Ht=async(e,t)=>a(fe(e),{...t,method:"DELETE"}),me=e=>`/v1/media/${e}`,Dt=async(e,t)=>a(me(e),{...t,method:"GET"}),de=(e,t)=>{let r=new URLSearchParams;Object.entries(t||{}).forEach(([o,s])=>{s!==void 0&&r.append(o,s===null?"null":String(s))});let n=r.toString();return n.length>0?`/v1/media/${e}/transcript?${n}`:`/v1/media/${e}/transcript`},Wt=async(e,t,r)=>a(de(e,t),{...r,method:"GET"}),ue=e=>`/v1/media/${e}/context`,Vt=async(e,t)=>a(ue(e),{...t,method:"GET"}),le=(e,t)=>{let r=new URLSearchParams;Object.entries(t||{}).forEach(([o,s])=>{s!==void 0&&r.append(o,s===null?"null":String(s))});let n=r.toString();return n.length>0?`/v1/media/${e}/detect-subjects?${n}`:`/v1/media/${e}/detect-subjects`},zt=async(e,t,r)=>a(le(e,t),{...r,method:"POST"}),ge=e=>`/v1/media/${e}/matte`,Xt=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(ge(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},ye=(e,t)=>{let r=new URLSearchParams;Object.entries(t||{}).forEach(([o,s])=>{s!==void 0&&r.append(o,s===null?"null":String(s))});let n=r.toString();return n.length>0?`/v1/media/${e}/facts?${n}`:`/v1/media/${e}/facts`},Yt=async(e,t,r)=>a(ye(e,t),{...r,method:"GET"}),xe=e=>`/v1/media/${e}/facts`,Zt=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(xe(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},Re=e=>`/v1/media/${e}/transcript/analyze`,Qt=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(Re(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},Ce=()=>"/v1/timeline-analysis",er=async(e,t)=>{let r=n=>{if(!n)return{};if(n instanceof Headers)return Object.fromEntries(n.entries());if(Symbol.iterator in n)return Object.fromEntries(Array.from(n,s=>Array.from(s)));let o={};for(let[s,i]of Object.entries(n))i!==void 0&&(o[s]=i);return o};return a(Ce(),{...t,method:"POST",headers:{"Content-Type":"application/json",...r(t?.headers)},body:JSON.stringify(e)})};var Ee={};y(Ee,{createProject:()=>rr,deleteProject:()=>sr,getCreateProjectUrl:()=>Se,getDeleteProjectUrl:()=>qe,getGetProjectContextUrl:()=>ke,getGetProjectUrl:()=>he,getListProjectsUrl:()=>Pe,getPatchProjectUrl:()=>ve,getProject:()=>or,getProjectContext:()=>ir,listProjects:()=>tr,patchProject:()=>nr});var Pe=e=>{let t=new URLSearchParams;Object.entries(e||{}).forEach(([n,o])=>{o!==void 0&&t.append(n,o===null?"null":String(o))});let r=t.toString();return r.length>0?`/v1/projects?${r}`:"/v1/projects"},tr=async(e,t)=>a(Pe(e),{...t,method:"GET"}),Se=()=>"/v1/projects",rr=async(e,t)=>{let r=n=>{if(!n)return{};if(n instanceof Headers)return Object.fromEntries(n.entries());if(Symbol.iterator in n)return Object.fromEntries(Array.from(n,s=>Array.from(s)));let o={};for(let[s,i]of Object.entries(n))i!==void 0&&(o[s]=i);return o};return a(Se(),{...t,method:"POST",headers:{"Content-Type":"application/json",...r(t?.headers)},body:JSON.stringify(e)})},he=e=>`/v1/projects/${e}`,or=async(e,t)=>a(he(e),{...t,method:"GET"}),ve=e=>`/v1/projects/${e}`,nr=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(ve(e),{...r,method:"PATCH",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},qe=e=>`/v1/projects/${e}`,sr=async(e,t)=>a(qe(e),{...t,method:"DELETE"}),ke=e=>`/v1/projects/${e}/context`,ir=async(e,t)=>a(ke(e),{...t,method:"GET"});var Ke={};y(Ke,{cancelRender:()=>mr,createRender:()=>ar,getCancelRenderUrl:()=>we,getCreateRenderUrl:()=>Te,getGetRenderUrl:()=>Oe,getListProjectRendersUrl:()=>Ie,getPreviewClipUrl:()=>je,getRefreshRenderUrlUrl:()=>Me,getRender:()=>fr,getRetryRenderUrl:()=>Ae,getStreamRenderUrl:()=>Ue,listProjectRenders:()=>pr,previewClip:()=>cr,refreshRenderUrl:()=>ur,retryRender:()=>dr,streamRender:()=>lr});var Te=e=>`/v1/projects/${e}/renders`,ar=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(Te(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},Ie=(e,t)=>{let r=new URLSearchParams;Object.entries(t||{}).forEach(([o,s])=>{s!==void 0&&r.append(o,s===null?"null":String(s))});let n=r.toString();return n.length>0?`/v1/projects/${e}/renders?${n}`:`/v1/projects/${e}/renders`},pr=async(e,t,r)=>a(Ie(e,t),{...r,method:"GET"}),je=e=>`/v1/projects/${e}/preview-clip`,cr=async(e,t,r)=>{let n=o=>{if(!o)return{};if(o instanceof Headers)return Object.fromEntries(o.entries());if(Symbol.iterator in o)return Object.fromEntries(Array.from(o,i=>Array.from(i)));let s={};for(let[i,p]of Object.entries(o))p!==void 0&&(s[i]=p);return s};return a(je(e),{...r,method:"POST",headers:{"Content-Type":"application/json",...n(r?.headers)},body:JSON.stringify(t)})},Oe=(e,t)=>`/v1/projects/${e}/renders/${t}`,fr=async(e,t,r)=>a(Oe(e,t),{...r,method:"GET"}),we=(e,t)=>`/v1/projects/${e}/renders/${t}/cancel`,mr=async(e,t,r)=>a(we(e,t),{...r,method:"POST"}),Ae=(e,t)=>`/v1/projects/${e}/renders/${t}/retry`,dr=async(e,t,r)=>a(Ae(e,t),{...r,method:"POST"}),Me=(e,t)=>`/v1/projects/${e}/renders/${t}/refresh-url`,ur=async(e,t,r)=>a(Me(e,t),{...r,method:"POST"}),Ue=(e,t)=>`/v1/projects/${e}/renders/${t}/stream`,lr=async(e,t,r)=>a(Ue(e,t),{...r,method:"GET"});var Je={};y(Je,{createSession:()=>Rr,deleteSession:()=>br,getCreateSessionUrl:()=>Le,getDeleteSessionUrl:()=>Ge,getGetMuxJobUrl:()=>$e,getGetSessionUrl:()=>Ne,getListSessionsUrl:()=>Be,getMuxJob:()=>Sr,getSession:()=>Cr,getTriggerMuxJobUrl:()=>Fe,listSessions:()=>xr,triggerMuxJob:()=>Pr});var Be=e=>{let t=new URLSearchParams;Object.entries(e||{}).forEach(([n,o])=>{o!==void 0&&t.append(n,o===null?"null":String(o))});let r=t.toString();return r.length>0?`/v1/sessions?${r}`:"/v1/sessions"},xr=async(e,t)=>a(Be(e),{...t,method:"GET"}),Le=()=>"/v1/sessions",Rr=async(e,t)=>{let r=n=>{if(!n)return{};if(n instanceof Headers)return Object.fromEntries(n.entries());if(Symbol.iterator in n)return Object.fromEntries(Array.from(n,s=>Array.from(s)));let o={};for(let[s,i]of Object.entries(n))i!==void 0&&(o[s]=i);return o};return a(Le(),{...t,method:"POST",headers:{"Content-Type":"application/json",...r(t?.headers)},body:JSON.stringify(e)})},Ne=e=>`/v1/sessions/${e}`,Cr=async(e,t)=>a(Ne(e),{...t,method:"GET"}),Ge=e=>`/v1/sessions/${e}`,br=async(e,t)=>a(Ge(e),{...t,method:"DELETE"}),Fe=e=>`/v1/sessions/${e}/mux-job`,Pr=async(e,t)=>a(Fe(e),{...t,method:"POST"}),$e=e=>`/v1/sessions/${e}/mux-job`,Sr=async(e,t)=>a($e(e),{...t,method:"GET"});var Tr=[3,4];var k="X-CueFrame-Client";var Ir=/^[A-Za-z0-9][A-Za-z0-9._+-]{0,31}$/,jr=["web","console","clips"];function Or(e,t){return jr.includes(e)===(t==="browser")}function _e(e){if(!Ir.test(e.version))throw new Error(`${k} cannot carry the version ${JSON.stringify(e.version)}.`);if(!Or(e.surface,e.os))throw new Error(`${k} cannot carry ${e.surface} on ${e.os}.`);return`${e.surface}/${e.version}/${e.os}`}function He(e){return e==="darwin"?"macos":e==="win32"?"windows":e==="linux"?"linux":"unknown"}import{readFileSync as wr,writeFileSync as Ar,mkdirSync as Mr,existsSync as Ur}from"fs";import{join as De}from"path";import{homedir as Kr}from"os";var m={Success:0,UserError:2,ApiClientError:3,ApiServerError:4,NetworkError:5,PaymentRequired:6};function w(e){if(e instanceof u){if(e.status===402)return m.PaymentRequired;if(e.status>=500)return m.ApiServerError;if(e.status>=400)return m.ApiClientError}let t=e?.exitCode;return typeof t=="number"?t:m.NetworkError}function XP(e){return e===402?m.PaymentRequired:e>=500?m.ApiServerError:e>=400?m.ApiClientError:m.Success}function S(e){process.exit(e)}var We=De(Kr(),".cueframe"),E=De(We,"auth.json"),R={local:"http://127.0.0.1:3211",prod:"https://api.cueframe.ai"},Br="prod";function rS(e=Br){return process.env.CUEFRAME_API_URL??R[e]??R.prod}var h=class extends Error{constructor(r,n){super(n);this.code=r;this.name="AuthStoreError"}code;exitCode=m.UserError};function oS(e){if(!/^cf_(?:live|test)_[A-Za-z0-9_-]{8,}$/.test(e))throw new h("auth_invalid","Invalid API key. Expected a key beginning with cf_live_ or cf_test_.")}function Ve(){if(!Ur(E))return{targets:{}};let e=wr(E,"utf-8");try{return JSON.parse(e)}catch{throw new h("auth_config_corrupt",`${E} is corrupt and cannot be parsed. Delete it and re-run \`cueframe login\`.`)}}function Lr(e){Mr(We,{recursive:!0,mode:448}),Ar(E,JSON.stringify(e,null,2),{mode:384})}function nS(e,t="prod",r){let n=Ve(),o=R[t]??R.prod;n.targets[t]={apiKey:e,apiUrl:r??o},Lr(n)}function ze(e="prod"){let t=process.env.CUEFRAME_API_KEY,r=process.env.CUEFRAME_API_URL;if(t)return{apiKey:t,apiUrl:r??R[e]??R.prod};let o=Ve().targets[e];if(!o)throw new h("auth_missing",`No auth configured for target "${e}". Run \`cueframe login --target ${e}\` (browser sign-in) or \`cueframe auth <api-key> --target ${e}\` (CI / headless).`);return o}function Nr(){return{[k]:_e({surface:"cli",version:"0.8.3",os:He(process.platform)})}}function Xe(e){let{apiKey:t,apiUrl:r}=ze(e);I({baseUrl:r,apiKey:t,headers:Nr()})}function T(e){let t=e instanceof u?`${e.message} (${e.code}${e.status?`, ${e.status}`:""})`:e instanceof Error?e.message:String(e),r=O(e);return r?`${t}
9
- \u2192 ${r}`:t}import Gr from"ora";import Fr from"pino";var $r="v1",Ye=Fr({level:"trace",base:{schemaVersion:$r},messageKey:"event",timestamp:()=>`,"ts":${Date.now()}`,formatters:{level:()=>({_:0})}});function A(e,t){return Gr({text:e,isSilent:!!t}).start()}function C(e,t,r={}){e.json&&Ye.info(r,t)}function uS(e,t,r){if(e.json){console.log(JSON.stringify(t,null,2));return}r()}function M(e,t,r,n){let o=r instanceof Error?r.message:String(r),s=typeof r?.code=="string"?r.code:void 0,i=r?.status;e.json?Ye.info({phase:t,message:o,...s?{code:s}:{},...typeof i=="number"?{status:i}:{},exitCode:n},"error"):process.stderr.write(`\u2716 ${t}: ${T(r)}
10
- `)}function U(e,t,r,n){e.json&&M(e,t,r,n)}function lS(e,t){t.json||console.log(e)}function Jr(e){for(let t=0;t<e.length;t++){let r=e.charCodeAt(t);if(r<=31||r===127)return!0}return!1}function Qe(e,t,r){e.length===0&&Ze(`${t} is empty.`,r),Jr(e)&&Ze(`${t} contains a control character (newline, tab, or null byte). Identifiers must be plain text \u2014 check for a stray copy-paste artifact.`,r)}function Ze(e,t){M(t,"preflight",new Error(e),m.UserError),S(m.UserError)}var _r=5e3,K=300*1e3;async function vS(e,t){if(Qe(e,"mediaItemId",t),t.dryRun){C(t,"analyze_dry_run",{mediaItemId:e,target:t.target,wait:!!t.wait,wouldCall:"POST /v1/media/:id/suggestions"}),t.json||console.log(`[dry-run] Would trigger clip analysis for ${e} on ${t.target}.`);return}Xe(t.target),C(t,"analyze_prepare",{mediaItemId:e,target:t.target,wait:!!t.wait});let r=A("Triggering clip analysis\u2026",t.json),n;try{n=await P.suggestBriefs(e),r.succeed(`Analysis ${n.alreadyRunning?"already running":"started"}`)}catch(i){r.fail(`Failed to start analysis: ${T(i)}`),U(t,"analyze_prepare",i,w(i)),S(w(i))}if(C(t,"analyze_ready",{mediaItemId:e,status:n.status,alreadyRunning:!!n.alreadyRunning}),!t.wait){t.json||console.log(`
11
- Run \`cueframe clips ${e}\` to check results.`);return}let o=A("Waiting for analysis to complete\u2026",t.json),s=Date.now();for(;;){await new Promise(i=>setTimeout(i,_r)),Date.now()-s>K&&(o.fail(`Timed out after ${Math.round(K/1e3)}s. Run \`cueframe clips ${e}\` to check later.`),U(t,"analyze_progress",new Error(`Analysis did not complete within ${Math.round(K/1e3)}s`),m.UserError),S(m.UserError));try{let i=await P.listMediaSuggestions(e);if(i.suggestions.length>0){o.succeed(`Analysis complete \u2014 ${i.suggestions.length} clips found`),C(t,"analyze_complete",{mediaItemId:e,durationMs:Date.now()-s,suggestionCount:i.suggestions.length,suggestions:i.suggestions}),t.json||i.suggestions.forEach((d,c)=>{let f=(d.trim.end-d.trim.start).toFixed(1);console.log(`
12
- ${c+1}. ${d.title} (${d.id})`),console.log(` ${d.trim.start.toFixed(1)}s \u2013 ${d.trim.end.toFixed(1)}s (${f}s) score: ${d.score}`),console.log(` ${d.reason}`)});return}let p=Math.round((Date.now()-s)/1e3);o.text=`Waiting for analysis\u2026 (${p}s)`,C(t,"analyze_progress",{mediaItemId:e,elapsedSec:p})}catch{}}}export{u as a,I as b,L as c,a as d,O as e,st as f,P as g,Y as h,re as i,be as j,Ee as k,Ke as l,Je as m,Tr as n,m as o,w as p,XP as q,S as r,rS as s,oS as t,nS as u,Nr as v,Xe as w,T as x,A as y,C as z,uS as A,M as B,U as C,lS as D,Qe as E,vS as F};