@clipwright/core 0.34.0 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +107 -0
- package/README.md +3 -1
- package/dist/account-actors.d.ts +173 -14
- package/dist/account-actors.js +142 -10
- package/dist/account-actors.js.map +1 -1
- package/dist/actor-bounds.d.ts +4 -0
- package/dist/actor-bounds.js +4 -0
- package/dist/actor-bounds.js.map +1 -1
- package/dist/actors.d.ts +31 -0
- package/dist/actors.js +26 -0
- package/dist/actors.js.map +1 -1
- package/dist/assets.d.ts +17 -1
- package/dist/assets.js +19 -2
- package/dist/assets.js.map +1 -1
- package/dist/billing-terms.d.ts +69 -0
- package/dist/billing-terms.js +8 -0
- package/dist/billing-terms.js.map +1 -1
- package/dist/contract-dispositions.d.ts +485 -1
- package/dist/contract-dispositions.js +27 -3
- package/dist/contract-dispositions.js.map +1 -1
- package/dist/contracts/v1/workflow-brief.d.ts +1420 -0
- package/dist/contracts/v1/workflow-brief.js +4 -0
- package/dist/contracts/v1/workflow-brief.js.map +1 -1
- package/dist/contracts/v1/workflow-catalog.d.ts +2141 -105
- package/dist/contracts/v1/workflow-catalog.js +4 -2
- package/dist/contracts/v1/workflow-catalog.js.map +1 -1
- package/dist/contracts/v1/workflow-client.d.ts +1631 -3
- package/dist/contracts/v1/workflow-client.js +6 -3
- package/dist/contracts/v1/workflow-client.js.map +1 -1
- package/dist/contracts/v1/workflow-execution.d.ts +161 -9
- package/dist/contracts/v1/workflow-execution.js +15 -7
- package/dist/contracts/v1/workflow-execution.js.map +1 -1
- package/dist/contracts/v1/workflow-plan.d.ts +3167 -142
- package/dist/contracts/v1/workflow-primitives.d.ts +3 -1
- package/dist/contracts/v1/workflow-primitives.js +1 -1
- package/dist/contracts/v1/workflow-primitives.js.map +1 -1
- package/dist/contracts/v1/workflow-run-read.d.ts +114 -1
- package/dist/edit-billing.d.ts +12 -0
- package/dist/edit-billing.js +8 -0
- package/dist/edit-billing.js.map +1 -1
- package/dist/edit-long-form.d.ts +1 -1
- package/dist/edit-long-form.js +12 -2
- package/dist/edit-long-form.js.map +1 -1
- package/dist/endpoint-notes.d.ts +3 -0
- package/dist/endpoint-notes.js +66 -0
- package/dist/endpoint-notes.js.map +1 -0
- package/dist/endpoints.d.ts +4 -0
- package/dist/endpoints.js +13 -0
- package/dist/endpoints.js.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +6 -0
- package/dist/errors.js.map +1 -1
- package/dist/face-billing.d.ts +55 -0
- package/dist/face-billing.js +22 -0
- package/dist/face-billing.js.map +1 -1
- package/dist/faceless-price.d.ts +26 -2
- package/dist/faceless-price.js +33 -6
- package/dist/faceless-price.js.map +1 -1
- package/dist/faceless-public.d.ts +6 -1
- package/dist/faceless-public.js +2 -2
- package/dist/faceless-public.js.map +1 -1
- package/dist/generations.js +15 -16
- package/dist/generations.js.map +1 -1
- package/dist/idempotency.d.ts +2 -0
- package/dist/idempotency.js +7 -4
- package/dist/idempotency.js.map +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -1
- package/dist/long-form-pricing.d.ts +7 -4
- package/dist/long-form-pricing.js +13 -10
- package/dist/long-form-pricing.js.map +1 -1
- package/dist/long-form-revision.js +1 -1
- package/dist/long-form-revision.js.map +1 -1
- package/dist/openapi.d.ts +154 -0
- package/dist/openapi.js +334 -0
- package/dist/openapi.js.map +1 -0
- package/dist/pacing.d.ts +15 -0
- package/dist/pacing.js +30 -0
- package/dist/pacing.js.map +1 -1
- package/dist/parts-pricing.d.ts +84 -0
- package/dist/parts-pricing.js +105 -0
- package/dist/parts-pricing.js.map +1 -0
- package/dist/presenter-beats.d.ts +45 -0
- package/dist/presenter-beats.js +144 -0
- package/dist/presenter-beats.js.map +1 -0
- package/dist/prices.d.ts +98 -0
- package/dist/prices.js +189 -0
- package/dist/prices.js.map +1 -0
- package/dist/public-responses.d.ts +23 -0
- package/dist/public-responses.js +11 -0
- package/dist/public-responses.js.map +1 -0
- package/dist/reference-analysis.d.ts +683 -0
- package/dist/reference-analysis.js +91 -0
- package/dist/reference-analysis.js.map +1 -0
- package/dist/reference-kinds.d.ts +6 -0
- package/dist/reference-kinds.js +8 -0
- package/dist/reference-kinds.js.map +1 -0
- package/dist/reference-profile.d.ts +633 -0
- package/dist/reference-profile.js +151 -0
- package/dist/reference-profile.js.map +1 -0
- package/dist/reference-staging.d.ts +571 -0
- package/dist/reference-staging.js +151 -0
- package/dist/reference-staging.js.map +1 -0
- package/dist/reference-voice.d.ts +305 -0
- package/dist/reference-voice.js +108 -0
- package/dist/reference-voice.js.map +1 -0
- package/dist/resolved-timeline.d.ts +53 -1
- package/dist/resolved-timeline.js +50 -4
- package/dist/resolved-timeline.js.map +1 -1
- package/dist/run-static-warnings.js +14 -5
- package/dist/run-static-warnings.js.map +1 -1
- package/dist/runs.d.ts +75 -3
- package/dist/runs.js +6 -1
- package/dist/runs.js.map +1 -1
- package/dist/skills.d.ts +1805 -24
- package/dist/skills.js +129 -19
- package/dist/skills.js.map +1 -1
- package/dist/templates/callout.d.ts +2 -2
- package/dist/templates/callout.js +6 -6
- package/dist/templates/callout.js.map +1 -1
- package/dist/templates/checklist.js +2 -2
- package/dist/templates/checklist.js.map +1 -1
- package/dist/templates/index.d.ts +14 -7
- package/dist/templates/index.js +29 -17
- package/dist/templates/index.js.map +1 -1
- package/dist/templates/notification.js +2 -2
- package/dist/templates/notification.js.map +1 -1
- package/dist/templates/phone-call.d.ts +3 -0
- package/dist/templates/phone-call.js +14 -7
- package/dist/templates/phone-call.js.map +1 -1
- package/dist/templates/progress.js +2 -2
- package/dist/templates/progress.js.map +1 -1
- package/dist/templates/sounds.d.ts +357 -7
- package/dist/templates/sounds.js +34 -12
- package/dist/templates/sounds.js.map +1 -1
- package/dist/ugc-call.d.ts +89 -0
- package/dist/ugc-call.js +111 -0
- package/dist/ugc-call.js.map +1 -0
- package/dist/ugc-framing.d.ts +26 -0
- package/dist/ugc-framing.js +64 -0
- package/dist/ugc-framing.js.map +1 -0
- package/dist/ugc-layers.d.ts +5 -1
- package/dist/ugc-layers.js +6 -1
- package/dist/ugc-layers.js.map +1 -1
- package/dist/vendor-response.d.ts +4 -0
- package/dist/vendor-response.js +12 -0
- package/dist/vendor-response.js.map +1 -1
- package/dist/voice-admission.d.ts +409 -0
- package/dist/voice-listing.js +7 -1
- package/dist/voice-listing.js.map +1 -1
- package/dist/voice-pace.d.ts +34 -0
- package/dist/voice-pace.generated.json +72 -0
- package/dist/voice-pace.js +34 -0
- package/dist/voice-pace.js.map +1 -0
- package/dist/voices.d.ts +21 -8
- package/dist/voices.js +44 -19
- package/dist/voices.js.map +1 -1
- package/dist/workflows/catalog.js +2 -1
- package/dist/workflows/catalog.js.map +1 -1
- package/dist/workflows/index.d.ts +2 -0
- package/dist/workflows/index.js +2 -0
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/methods/faceless-explainer.d.ts +377 -10
- package/dist/workflows/methods/kinetic-launch.d.ts +377 -10
- package/dist/workflows/methods/product-image-story.d.ts +377 -10
- package/dist/workflows/methods/reference-remake.d.ts +870 -0
- package/dist/workflows/methods/reference-remake.js +26 -0
- package/dist/workflows/methods/reference-remake.js.map +1 -0
- package/dist/workflows/methods/shared.d.ts +377 -10
- package/dist/workflows/methods/ugc-faq-answer.d.ts +377 -10
- package/dist/workflows/methods/ugc-product-intro.d.ts +377 -10
- package/dist/workflows/methods/website-proof-demo.d.ts +377 -10
- package/dist/workflows/reference-remake.d.ts +663 -0
- package/dist/workflows/reference-remake.js +598 -0
- package/dist/workflows/reference-remake.js.map +1 -0
- package/dist/workflows/validate.js +7 -4
- package/dist/workflows/validate.js.map +1 -1
- package/package.json +8 -2
package/CHANGELOG.md
CHANGED
|
@@ -18,6 +18,113 @@ listed under.
|
|
|
18
18
|
|
|
19
19
|
## [Unreleased]
|
|
20
20
|
|
|
21
|
+
## [0.35.0] - 2026-10-30
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- The texts an agent reads describe the `parts-v1` tariff (#933). The `call` field says the call adds production
|
|
26
|
+
seconds and that a live-avatar still has its own price; the templates description and the remake plan's tariff
|
|
27
|
+
note drop the retired per-second rate. The MCP server's SKILL.md and the CLI README point to `list_prices` and the
|
|
28
|
+
quotes instead of fixed faceless prices, and the `quote_ugc` example shows `price_lines` for 12 s.
|
|
29
|
+
- *Dashboard:* /pricing lists only the presenter a request can get, and prints single images and clips as price
|
|
30
|
+
ranges per resolution without model names (#800). Two comparison pages are rewritten from the other products'
|
|
31
|
+
sites as read on 2026-10-30.
|
|
32
|
+
|
|
33
|
+
- *Server-side:* `make_ugc` is priced by its parts, one tariff `parts-v1` for short and long videos (#800): 12 credits
|
|
34
|
+
for every second a presenter take fills on HeyGen (22 on OmniHuman), plus 1 for every second of the finished video,
|
|
35
|
+
plus 400 for each live-avatar still of a call, at least 50 for a delivered video. A plain 35 s video costs 455
|
|
36
|
+
instead of 1 050. The quote itemizes it in `price_lines` and names `minimum_credits`; the terms are frozen at
|
|
37
|
+
admission, so a run admitted before keeps its own.
|
|
38
|
+
- *Server-side:* `analyze_reference` costs 70 credits (#927): held at the start and charged once the analysis
|
|
39
|
+
succeeds; a failed analysis costs nothing, and starting it again on the same asset answers the same analysis for
|
|
40
|
+
free. The analysis carries `credits_reserved`, `credits_charged` and `balance_after_credits`.
|
|
41
|
+
- *Server-side:* single generations are priced at ×2.5 of their cheapest route instead of ×2: an image from 6 credits,
|
|
42
|
+
a clip from 6 credits a second. `seedance-2.0-mini` is rendered by one route only.
|
|
43
|
+
- *Server-side:* `make_faceless` is priced by its parts, tariff `faceless-parts-v1` (#800): 7 credits for each picture
|
|
44
|
+
we generate, the opening clip's still included, 49 for the opening clip and 1 for every second of the delivered
|
|
45
|
+
video, at least 50. Your own pictures are not charged. The quote is the most a selection is charged: 212 at 30 s,
|
|
46
|
+
356 at 90 s, instead of 350 and 420. `faceless_billing` names `images` and `imageCredits`; a run admitted before
|
|
47
|
+
keeps its tariff.
|
|
48
|
+
- *Server-side:* edits and personal actors are repriced at ×2.5 of their cost (#800): a revision's new picture 7, clip
|
|
49
|
+
49, clip with a new picture 56, render 13, and a shot candidate the same unit prices; an actor's portrait 4 and each
|
|
50
|
+
other format 8 at `medium`, 12 and 18 at `high`. Runs admitted before keep their snapshot.
|
|
51
|
+
|
|
52
|
+
### Added
|
|
53
|
+
|
|
54
|
+
- *Server-side:* `POST /v1/reference-analyses/quote`, the `quote_analysis` tool and `ClipwrightClient.quoteAnalysis()`
|
|
55
|
+
price an analysis before it starts (#927).
|
|
56
|
+
- *Server-side:* every settled run carries `balance_after_credits`, the account's balance read in the transaction
|
|
57
|
+
that settled it (#927).
|
|
58
|
+
|
|
59
|
+
- *Server-side:* `GET /v1/public/prices` lists the price of every action in credits, without a key: one entry per tool
|
|
60
|
+
and variant, its price as lines of credits per unit plus a minimum, or a formula; free tools are listed at 0. No price
|
|
61
|
+
changed (#927).
|
|
62
|
+
- The `list_prices` tool and `ClipwrightClient.listPrices()` read that list, and the description of every paid tool
|
|
63
|
+
ends with its price line, built from the same list.
|
|
64
|
+
- `@clipwright/core` exports `PRICE_LIST`, `priceLine` and `pricesResponse`, with the constants the list reads:
|
|
65
|
+
`CREDITS_PER_SECOND`, `ACTOR_UNIT_CREDITS`, `EDIT_UNIT_PRICES`, `EDIT_RENDER_PRICE`, `EDIT_ZERO_UNIT_PRICE` and the
|
|
66
|
+
numbers of the faceless tariff.
|
|
67
|
+
|
|
68
|
+
- *Server-side:* `GET /openapi.json` serves an OpenAPI 3.1 description of the REST API without a key: every public
|
|
69
|
+
route with its request and response schemas, the error envelope and `warnings[]`. The API's own tests check
|
|
70
|
+
their real responses against it.
|
|
71
|
+
- `@clipwright/core/openapi` exports `buildOpenApiDocument()` and the route marking `OPENAPI_ROUTES`;
|
|
72
|
+
`@clipwright/core` exports `ENDPOINT_NOTES`, `healthResponse` and `publicSkillsResponse`.
|
|
73
|
+
- `make_ugc` takes `voice_pace` (0.7–1.2): `eleven_flash_v2_5` and `eleven_turbo_v2_5` get it as their speed,
|
|
74
|
+
`gemini-3.8-flash-tts` as a "speaking rapidly" or "speaking slowly" style with a warning. `eleven_v4` has no speed
|
|
75
|
+
setting: it gets no speed, and a `voice_pace` other than 1 is named in `warnings[]` (#890).
|
|
76
|
+
- `list_voices` gives each English voice on `eleven_v4` its measured pace, `words_per_second`. On that model the voice
|
|
77
|
+
sets the pace, so pick the voice nearest a reference presenter's pace (#890).
|
|
78
|
+
- *Server-side:* all ElevenLabs speech goes to `eleven_v4`, now the model of every preset, catalog voice and raw
|
|
79
|
+
`voice_id`. `tts_model: "eleven_v3"` is still accepted: the run speaks `eleven_v4` and `warnings[]` says so.
|
|
80
|
+
`eleven_v4` gives no pause for a `<break>` tag, so the tag is cut with a warning on the default path too.
|
|
81
|
+
- `make_ugc` takes `pause_trim`, targets in seconds per gap class: after synthesis a pause longer than its target is cut
|
|
82
|
+
down to it inside silence only, with a crossfade, and word timings move with the audio. A joint that would click is
|
|
83
|
+
kept and named in `warnings[]`.
|
|
84
|
+
- *Server-side:* a reference analysis measures the presenter's voice from the words it already transcribes: pace,
|
|
85
|
+
pauses in three layers, hinge pauses, pitch and loudness range, in the profile's new `voice` section.
|
|
86
|
+
`plan_reference_remake` sets `voice_pace` from it on a model with a speed. On `eleven_v4` it sets none and, when
|
|
87
|
+
the voice is more than 5% off the presenter, names the measured voices nearer the presenter's pace (#890).
|
|
88
|
+
- `@clipwright/core` exports `referenceVoice`, the schema of that section, and `narrationPaceFromVoice`.
|
|
89
|
+
|
|
90
|
+
- *Dashboard:* a public `/captions` page plays every caption style on the same presenter and the same words, each
|
|
91
|
+
with the description `tools/list` gives it; the `caption_style` description links to the page.
|
|
92
|
+
- `SKILL.md` names every caption style and tells the agent to ask whether the user wants captions, to offer three
|
|
93
|
+
or four fitting styles with the gallery link, and to take the style closest to a reference video's captions.
|
|
94
|
+
- *Server-side:* `hormozi` now matches the canonical look: Montserrat Black uppercase, white with a thick black outline,
|
|
95
|
+
one yellow (`#FFD93D`) keyword per cue, up to three words. The previous look (condensed Oswald, orange keyword, no
|
|
96
|
+
outline) is the new style `accent`. `hormozi` stays the default; there are 24 styles.
|
|
97
|
+
- *Server-side:* `make_ugc` takes `edit_sounds: true` on a run with `inserts` or `layout_windows`: a low sound plays on
|
|
98
|
+
every cut, to or from an insert, at a full-frame template's cut in or out and at a layout window's in and out, with
|
|
99
|
+
its peak on the cut. `template_sounds.edit` picks it from `swell_hit` (default), `whoosh_deep`, `whoosh_low`,
|
|
100
|
+
`boom_low`, `sub_drop`, `riser_boom` and `riser_hit`. A cut that already plays a template's whoosh or flash gets no
|
|
101
|
+
second sound. Without the field a run plays no edit sounds, as before; `edit_sounds` with nothing to cut, with
|
|
102
|
+
`template_sounds: false`, or `template_sounds.edit` without `edit_sounds`, is refused 400 by its path before any
|
|
103
|
+
hold. The price does not change.
|
|
104
|
+
- *Server-side:* new template sounds: a `pop` (`plop`) when a `tag` or a `callout` pops in, a `hangup` (`phone`) just
|
|
105
|
+
before an answered `phone_call` leaves, and `money` (`cash_register`, `coins`) when a `stat` with a currency sign in
|
|
106
|
+
its prefix or suffix counts up. `answer` adds `pickup`, `whoosh` adds `slide_quick` and `flash` adds `swish`.
|
|
107
|
+
`list_template_sounds` lists them. A run frozen before them keeps its sounds.
|
|
108
|
+
- *Server-side:* `make_ugc` takes `framing`, presenter sizes on their words: `close` (1.18 times larger about the face)
|
|
109
|
+
or `medium`, each a hard cut that settles over 8 frames, or with `transition: "flash"` a warm light leak over the cut.
|
|
110
|
+
It needs long-form qualification, works without captions, refuses overlap with inserts, layout windows and other framing,
|
|
111
|
+
and names in `warnings[]` a framing wholly under full-frame templates. With `edit_sounds`, each framing cut plays the
|
|
112
|
+
edit sound. `plan_reference_remake` turns a `punch_in` camera into a close framing and a flash into a speaking beat
|
|
113
|
+
into a flashed one.
|
|
114
|
+
- `create_actor` takes `from_actor_id` with `framing: "wide"`, `holding` (one or two objects, each with words, an
|
|
115
|
+
optional image asset of the object and a hand) or `setting`: it derives a new personal actor from a library actor or
|
|
116
|
+
your own, with the same face checked against the source. A face that does not match costs nothing. The price is the
|
|
117
|
+
usual per-image units. *Server-side:* the fields are open only where `CLIPWRIGHT_ACTOR_VIEWS` is on; elsewhere they
|
|
118
|
+
are refused 400 `rejected_field`. A wide derived actor's 9:16 is listed with `framing: "wide"`, and `make_ugc`
|
|
119
|
+
renders it as a wide view. `@clipwright/core` exports `storedActorSource`, `storedHoldingItem`,
|
|
120
|
+
`createActorDispositions`, `createActorRejectedFields` and `isActorViewsEnabled`.
|
|
121
|
+
|
|
122
|
+
### Changed
|
|
123
|
+
|
|
124
|
+
- *Server-side:* the template sound library is re-recorded from CC0 sounds the owner chose by ear: 25 of the 31 files
|
|
125
|
+
play a new recording under the same name; the rings, `glitch`, `switch_heavy` and `paper_swipe` stay as they were.
|
|
126
|
+
Every source is named in `THIRD_PARTY_NOTICES`.
|
|
127
|
+
|
|
21
128
|
## [0.34.0] - 2026-10-24
|
|
22
129
|
|
|
23
130
|
### Added
|
package/README.md
CHANGED
|
@@ -17,7 +17,9 @@ edit: `runShots`, `runEdit` and `saveRunEdit` are what the API emits and takes;
|
|
|
17
17
|
that a name a later API adds does not break it.
|
|
18
18
|
|
|
19
19
|
The `./idempotency` subpath export is separate because it pulls in a Node
|
|
20
|
-
built-in and would otherwise break bundlers targeting the browser.
|
|
20
|
+
built-in and would otherwise break bundlers targeting the browser. So is
|
|
21
|
+
`./openapi`: `buildOpenApiDocument()` builds the OpenAPI 3.1 document the API
|
|
22
|
+
serves at `GET /openapi.json` from the route registry and these schemas.
|
|
21
23
|
|
|
22
24
|
## Changelog
|
|
23
25
|
|
package/dist/account-actors.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { type ActorQuality } from "./actor-qualities.js";
|
|
2
|
+
import { type ActorQuality, type ActorQualityAccepted } from "./actor-qualities.js";
|
|
3
3
|
import { type AspectRatio } from "./skills.js";
|
|
4
4
|
/** Personal actors of an account. */
|
|
5
5
|
export { ACTOR_DEFAULT_QUALITY, ACTOR_QUALITIES_ACCEPTED, ACTOR_QUALITIES_KNOWN } from "./actor-qualities.js";
|
|
6
6
|
export type { ActorQuality, ActorQualityAccepted } from "./actor-qualities.js";
|
|
7
|
-
export { ACTOR_AGE_FLOOR, ACTOR_ASPECTS_KNOWN, ACTOR_DESCRIPTION_MAX_CHARS, ACTOR_GENDERS_ACCEPTED, ACTOR_GENDERS_KNOWN, ACTOR_MAX_AGE, ACTOR_MIN_AGE, ACTOR_NAME_MAX_CHARS, } from "./actor-bounds.js";
|
|
7
|
+
export { ACTOR_AGE_FLOOR, ACTOR_ASPECTS_KNOWN, ACTOR_DESCRIPTION_MAX_CHARS, ACTOR_GENDERS_ACCEPTED, ACTOR_GENDERS_KNOWN, ACTOR_HOLDING_DESCRIPTION_MAX_CHARS, ACTOR_HOLDING_MAX_ITEMS, ACTOR_MAX_AGE, ACTOR_MIN_AGE, ACTOR_NAME_MAX_CHARS, ACTOR_SETTING_MAX_CHARS, } from "./actor-bounds.js";
|
|
8
8
|
export type { ActorAspectKnown, ActorGender } from "./actor-bounds.js";
|
|
9
9
|
export declare const PERSONAL_ACTOR_ID_PREFIX = "actor_u_";
|
|
10
10
|
/** `actor_u_` plus 26 base32 characters (RFC 4648, lowercase): 128 random bits. */
|
|
@@ -32,36 +32,70 @@ export declare const ACTOR_SIZE_SET: {
|
|
|
32
32
|
readonly height: 1024;
|
|
33
33
|
};
|
|
34
34
|
};
|
|
35
|
+
export declare const ACTOR_VIEW_FRAMINGS: readonly ["wide"];
|
|
36
|
+
export declare const ACTOR_HANDS: readonly ["left", "right"];
|
|
37
|
+
/** The fields of a view derived from an actor (#898). */
|
|
38
|
+
export declare const ACTOR_VIEW_FIELDS: readonly ["from_actor_id", "framing", "holding", "setting"];
|
|
35
39
|
type AcceptedQualities = readonly [ActorQuality, ...ActorQuality[]];
|
|
36
40
|
/** The input for a given set of accepted qualities. */
|
|
37
41
|
export declare function createActorInputWith<const Q extends AcceptedQualities>(accepted: Q, defaultQuality: Q[number]): z.ZodObject<{
|
|
38
|
-
description: z.ZodString
|
|
39
|
-
gender: z.ZodEnum<{
|
|
42
|
+
description: z.ZodOptional<z.ZodString>;
|
|
43
|
+
gender: z.ZodOptional<z.ZodEnum<{
|
|
40
44
|
female: "female";
|
|
41
45
|
male: "male";
|
|
42
|
-
}
|
|
43
|
-
approximate_age: z.ZodNumber
|
|
46
|
+
}>>;
|
|
47
|
+
approximate_age: z.ZodOptional<z.ZodNumber>;
|
|
44
48
|
name: z.ZodString;
|
|
45
49
|
aspect_ratios: z.ZodDefault<z.ZodArray<z.ZodEnum<{
|
|
46
50
|
"16:9": "16:9";
|
|
47
51
|
"1:1": "1:1";
|
|
48
52
|
"9:16": "9:16";
|
|
49
53
|
}>>>;
|
|
54
|
+
from_actor_id: z.ZodOptional<z.ZodString>;
|
|
55
|
+
framing: z.ZodOptional<z.ZodEnum<{
|
|
56
|
+
wide: "wide";
|
|
57
|
+
}>>;
|
|
58
|
+
holding: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
59
|
+
description: z.ZodString;
|
|
60
|
+
reference: z.ZodOptional<z.ZodObject<{
|
|
61
|
+
asset_id: z.ZodString;
|
|
62
|
+
}, z.core.$strict>>;
|
|
63
|
+
hand: z.ZodOptional<z.ZodEnum<{
|
|
64
|
+
left: "left";
|
|
65
|
+
right: "right";
|
|
66
|
+
}>>;
|
|
67
|
+
}, z.core.$strict>>>;
|
|
68
|
+
setting: z.ZodOptional<z.ZodString>;
|
|
50
69
|
quality: z.ZodDefault<z.ZodEnum<{ [k in Q[number]]: k; } extends infer T ? { [k in keyof T]: T[k]; } : never>>;
|
|
51
70
|
}, z.core.$strict>;
|
|
52
71
|
export declare const createActorInput: z.ZodObject<{
|
|
53
|
-
description: z.ZodString
|
|
54
|
-
gender: z.ZodEnum<{
|
|
72
|
+
description: z.ZodOptional<z.ZodString>;
|
|
73
|
+
gender: z.ZodOptional<z.ZodEnum<{
|
|
55
74
|
female: "female";
|
|
56
75
|
male: "male";
|
|
57
|
-
}
|
|
58
|
-
approximate_age: z.ZodNumber
|
|
76
|
+
}>>;
|
|
77
|
+
approximate_age: z.ZodOptional<z.ZodNumber>;
|
|
59
78
|
name: z.ZodString;
|
|
60
79
|
aspect_ratios: z.ZodDefault<z.ZodArray<z.ZodEnum<{
|
|
61
80
|
"16:9": "16:9";
|
|
62
81
|
"1:1": "1:1";
|
|
63
82
|
"9:16": "9:16";
|
|
64
83
|
}>>>;
|
|
84
|
+
from_actor_id: z.ZodOptional<z.ZodString>;
|
|
85
|
+
framing: z.ZodOptional<z.ZodEnum<{
|
|
86
|
+
wide: "wide";
|
|
87
|
+
}>>;
|
|
88
|
+
holding: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
89
|
+
description: z.ZodString;
|
|
90
|
+
reference: z.ZodOptional<z.ZodObject<{
|
|
91
|
+
asset_id: z.ZodString;
|
|
92
|
+
}, z.core.$strict>>;
|
|
93
|
+
hand: z.ZodOptional<z.ZodEnum<{
|
|
94
|
+
left: "left";
|
|
95
|
+
right: "right";
|
|
96
|
+
}>>;
|
|
97
|
+
}, z.core.$strict>>>;
|
|
98
|
+
setting: z.ZodOptional<z.ZodString>;
|
|
65
99
|
quality: z.ZodDefault<z.ZodEnum<{
|
|
66
100
|
high: "high";
|
|
67
101
|
medium: "medium";
|
|
@@ -73,18 +107,33 @@ export type CreateActorInput = z.infer<typeof createActorInput>;
|
|
|
73
107
|
export type CreateActorInputArgs = z.input<typeof createActorInput>;
|
|
74
108
|
/** Flat shape for MCP: the tool publishes the same schema the server checks. */
|
|
75
109
|
export declare const createActorInputShape: {
|
|
76
|
-
description: z.ZodString
|
|
77
|
-
gender: z.ZodEnum<{
|
|
110
|
+
description: z.ZodOptional<z.ZodString>;
|
|
111
|
+
gender: z.ZodOptional<z.ZodEnum<{
|
|
78
112
|
female: "female";
|
|
79
113
|
male: "male";
|
|
80
|
-
}
|
|
81
|
-
approximate_age: z.ZodNumber
|
|
114
|
+
}>>;
|
|
115
|
+
approximate_age: z.ZodOptional<z.ZodNumber>;
|
|
82
116
|
name: z.ZodString;
|
|
83
117
|
aspect_ratios: z.ZodDefault<z.ZodArray<z.ZodEnum<{
|
|
84
118
|
"16:9": "16:9";
|
|
85
119
|
"1:1": "1:1";
|
|
86
120
|
"9:16": "9:16";
|
|
87
121
|
}>>>;
|
|
122
|
+
from_actor_id: z.ZodOptional<z.ZodString>;
|
|
123
|
+
framing: z.ZodOptional<z.ZodEnum<{
|
|
124
|
+
wide: "wide";
|
|
125
|
+
}>>;
|
|
126
|
+
holding: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
127
|
+
description: z.ZodString;
|
|
128
|
+
reference: z.ZodOptional<z.ZodObject<{
|
|
129
|
+
asset_id: z.ZodString;
|
|
130
|
+
}, z.core.$strict>>;
|
|
131
|
+
hand: z.ZodOptional<z.ZodEnum<{
|
|
132
|
+
left: "left";
|
|
133
|
+
right: "right";
|
|
134
|
+
}>>;
|
|
135
|
+
}, z.core.$strict>>>;
|
|
136
|
+
setting: z.ZodOptional<z.ZodString>;
|
|
88
137
|
quality: z.ZodDefault<z.ZodEnum<{
|
|
89
138
|
high: "high";
|
|
90
139
|
medium: "medium";
|
|
@@ -94,6 +143,10 @@ export declare const actorUnitCredits: z.ZodObject<{
|
|
|
94
143
|
portrait: z.ZodNumber;
|
|
95
144
|
variant: z.ZodNumber;
|
|
96
145
|
}, z.core.$strip>;
|
|
146
|
+
/** Unit prices of a personal actor (owner's decision, clipwright#120). Admission copies them into the */
|
|
147
|
+
/** run's snapshot and settlement reads the snapshot, so a change here leaves old runs alone. ×2.5 over the S0 costs (owner, 29.10, */
|
|
148
|
+
/** #800): a portrait is a generate call ($0.0103 medium, $0.039 high), another format an edit ($0.024, $0.0581). */
|
|
149
|
+
export declare const ACTOR_UNIT_CREDITS: Readonly<Record<ActorQualityAccepted, z.infer<typeof actorUnitCredits>>>;
|
|
97
150
|
/** Unit prices and requested formats fixed at admission; settlement uses these, not the price table. */
|
|
98
151
|
export declare const actorPricingSnapshot: z.ZodObject<{
|
|
99
152
|
quality: z.ZodEnum<{
|
|
@@ -127,6 +180,43 @@ export declare const admittedActorPricingSnapshot: z.ZodObject<{
|
|
|
127
180
|
"9:16": "9:16";
|
|
128
181
|
}>>;
|
|
129
182
|
}, z.core.$strip>;
|
|
183
|
+
/** The source image admission resolved for `from_actor_id`: the worker reads these bytes, not a payload. */
|
|
184
|
+
export declare const storedActorSource: z.ZodObject<{
|
|
185
|
+
actor_id: z.ZodString;
|
|
186
|
+
scope: z.ZodEnum<{
|
|
187
|
+
account: "account";
|
|
188
|
+
clipwright: "clipwright";
|
|
189
|
+
}>;
|
|
190
|
+
key: z.ZodString;
|
|
191
|
+
sha256: z.ZodString;
|
|
192
|
+
width: z.ZodNumber;
|
|
193
|
+
height: z.ZodNumber;
|
|
194
|
+
framing: z.ZodEnum<{
|
|
195
|
+
close: "close";
|
|
196
|
+
wide: "wide";
|
|
197
|
+
}>;
|
|
198
|
+
}, z.core.$strip>;
|
|
199
|
+
export type StoredActorSource = z.infer<typeof storedActorSource>;
|
|
200
|
+
/** A held object as admitted: a `reference` carries the asset row admission found. */
|
|
201
|
+
export declare const storedHoldingItem: z.ZodObject<{
|
|
202
|
+
description: z.ZodString;
|
|
203
|
+
hand: z.ZodOptional<z.ZodEnum<{
|
|
204
|
+
left: "left";
|
|
205
|
+
right: "right";
|
|
206
|
+
}>>;
|
|
207
|
+
reference: z.ZodOptional<z.ZodObject<{
|
|
208
|
+
asset_id: z.ZodString;
|
|
209
|
+
}, z.core.$strip>>;
|
|
210
|
+
picture: z.ZodOptional<z.ZodObject<{
|
|
211
|
+
asset_id: z.ZodString;
|
|
212
|
+
key: z.ZodString;
|
|
213
|
+
mime: z.ZodEnum<{
|
|
214
|
+
"image/jpeg": "image/jpeg";
|
|
215
|
+
"image/png": "image/png";
|
|
216
|
+
}>;
|
|
217
|
+
}, z.core.$strip>>;
|
|
218
|
+
}, z.core.$strip>;
|
|
219
|
+
export type StoredHoldingItem = z.infer<typeof storedHoldingItem>;
|
|
130
220
|
/** A stored run input. Quality and formats must match the snapshot, or generation would diverge */
|
|
131
221
|
/** from the charge, so such a run does not read (`run_input_unreadable`, zero credits). */
|
|
132
222
|
export declare const storedCreateActorInput: z.ZodObject<{
|
|
@@ -161,6 +251,44 @@ export declare const storedCreateActorInput: z.ZodObject<{
|
|
|
161
251
|
"9:16": "9:16";
|
|
162
252
|
}>>;
|
|
163
253
|
}, z.core.$strip>;
|
|
254
|
+
from_actor_id: z.ZodOptional<z.ZodString>;
|
|
255
|
+
source_actor: z.ZodOptional<z.ZodObject<{
|
|
256
|
+
actor_id: z.ZodString;
|
|
257
|
+
scope: z.ZodEnum<{
|
|
258
|
+
account: "account";
|
|
259
|
+
clipwright: "clipwright";
|
|
260
|
+
}>;
|
|
261
|
+
key: z.ZodString;
|
|
262
|
+
sha256: z.ZodString;
|
|
263
|
+
width: z.ZodNumber;
|
|
264
|
+
height: z.ZodNumber;
|
|
265
|
+
framing: z.ZodEnum<{
|
|
266
|
+
close: "close";
|
|
267
|
+
wide: "wide";
|
|
268
|
+
}>;
|
|
269
|
+
}, z.core.$strip>>;
|
|
270
|
+
framing: z.ZodOptional<z.ZodEnum<{
|
|
271
|
+
wide: "wide";
|
|
272
|
+
}>>;
|
|
273
|
+
holding: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
274
|
+
description: z.ZodString;
|
|
275
|
+
hand: z.ZodOptional<z.ZodEnum<{
|
|
276
|
+
left: "left";
|
|
277
|
+
right: "right";
|
|
278
|
+
}>>;
|
|
279
|
+
reference: z.ZodOptional<z.ZodObject<{
|
|
280
|
+
asset_id: z.ZodString;
|
|
281
|
+
}, z.core.$strip>>;
|
|
282
|
+
picture: z.ZodOptional<z.ZodObject<{
|
|
283
|
+
asset_id: z.ZodString;
|
|
284
|
+
key: z.ZodString;
|
|
285
|
+
mime: z.ZodEnum<{
|
|
286
|
+
"image/jpeg": "image/jpeg";
|
|
287
|
+
"image/png": "image/png";
|
|
288
|
+
}>;
|
|
289
|
+
}, z.core.$strip>>;
|
|
290
|
+
}, z.core.$strip>>>;
|
|
291
|
+
setting: z.ZodOptional<z.ZodString>;
|
|
164
292
|
}, z.core.$strip>;
|
|
165
293
|
export type StoredCreateActorInput = z.infer<typeof storedCreateActorInput>;
|
|
166
294
|
export declare const createActorQuote: z.ZodObject<{
|
|
@@ -235,7 +363,11 @@ export type CreateActorDisposition = {
|
|
|
235
363
|
kind: "warned";
|
|
236
364
|
warning: string;
|
|
237
365
|
triggersWhen: "present";
|
|
366
|
+
} | {
|
|
367
|
+
kind: "rejected";
|
|
368
|
+
message: string;
|
|
238
369
|
};
|
|
370
|
+
type CreateActorField = keyof typeof createActorInput.shape;
|
|
239
371
|
export declare const CREATE_ACTOR_FIELD_DISPOSITIONS: {
|
|
240
372
|
readonly description: {
|
|
241
373
|
readonly kind: "implemented";
|
|
@@ -261,7 +393,31 @@ export declare const CREATE_ACTOR_FIELD_DISPOSITIONS: {
|
|
|
261
393
|
readonly kind: "implemented";
|
|
262
394
|
readonly provenBy: "egress";
|
|
263
395
|
};
|
|
396
|
+
readonly from_actor_id: {
|
|
397
|
+
readonly kind: "implemented";
|
|
398
|
+
readonly provenBy: "egress";
|
|
399
|
+
};
|
|
400
|
+
readonly framing: {
|
|
401
|
+
readonly kind: "implemented";
|
|
402
|
+
readonly provenBy: "egress";
|
|
403
|
+
};
|
|
404
|
+
readonly holding: {
|
|
405
|
+
readonly kind: "implemented";
|
|
406
|
+
readonly provenBy: "egress";
|
|
407
|
+
};
|
|
408
|
+
readonly setting: {
|
|
409
|
+
readonly kind: "implemented";
|
|
410
|
+
readonly provenBy: "egress";
|
|
411
|
+
};
|
|
264
412
|
};
|
|
413
|
+
export declare const ACTOR_VIEWS_DISABLED_MESSAGE = "is switched off on this deployment: deriving an actor from an actor is not available; create an actor from a description instead";
|
|
414
|
+
/** The registry with `CLIPWRIGHT_ACTOR_VIEWS` applied: switched off, the view fields are refused, not ignored. */
|
|
415
|
+
export declare function createActorDispositions(viewsEnabled: boolean): Record<CreateActorField, CreateActorDisposition>;
|
|
416
|
+
/** Present fields whose disposition is `rejected`, in registry order, for `rejectedFieldBody`. */
|
|
417
|
+
export declare function createActorRejectedFields(input: Readonly<Record<string, unknown>>, dispositions: Readonly<Record<string, CreateActorDisposition>>): {
|
|
418
|
+
field: string;
|
|
419
|
+
message: string;
|
|
420
|
+
}[];
|
|
265
421
|
/** Admission warnings come only from the registry; written to `runs.warnings`, not recomputed on read. */
|
|
266
422
|
export declare function createActorAdmissionWarnings(input: Readonly<Record<string, unknown>>, dispositions?: Readonly<Record<string, CreateActorDisposition>>): string[];
|
|
267
423
|
/** `create_actor` run failure codes, each charging zero credits. The `error` column reads `code: text`. */
|
|
@@ -275,6 +431,9 @@ export declare const CREATE_ACTOR_RUN_ERRORS: {
|
|
|
275
431
|
readonly actor_generation_disabled: "actor generation is disabled right now; no actor was created and nothing was charged";
|
|
276
432
|
readonly actor_run_interrupted: "the run stopped before it finished; no actor was created and nothing was charged";
|
|
277
433
|
readonly actor_spend_refused: "our spend guard refused the paid call; no actor was created and nothing was charged. Retry later";
|
|
434
|
+
readonly actor_identity_not_kept: "the edited portrait did not keep the source actor's face; no actor was created and nothing was charged";
|
|
435
|
+
readonly actor_source_unreadable: "the source actor or a held object's picture could not be read; no actor was created and nothing was charged";
|
|
436
|
+
readonly actor_views_disabled: "deriving an actor from an actor is disabled right now; no actor was created and nothing was charged";
|
|
278
437
|
};
|
|
279
438
|
export type CreateActorRunErrorCode = keyof typeof CREATE_ACTOR_RUN_ERRORS;
|
|
280
439
|
export declare const CREATE_ACTOR_RUN_ERROR_CODES: CreateActorRunErrorCode[];
|
package/dist/account-actors.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { ACTOR_DEFAULT_QUALITY, ACTOR_QUALITIES_ACCEPTED, ACTOR_QUALITIES_KNOWN, } from "./actor-qualities.js";
|
|
3
|
-
import { ACTOR_AGE_FLOOR, ACTOR_ASPECTS_KNOWN, ACTOR_DESCRIPTION_MAX_CHARS, ACTOR_GENDERS_ACCEPTED, ACTOR_GENDERS_KNOWN, ACTOR_MAX_AGE, ACTOR_MIN_AGE, ACTOR_NAME_MAX_CHARS, } from "./actor-bounds.js";
|
|
4
|
-
import {
|
|
3
|
+
import { ACTOR_AGE_FLOOR, ACTOR_ASPECTS_KNOWN, ACTOR_DESCRIPTION_MAX_CHARS, ACTOR_GENDERS_ACCEPTED, ACTOR_GENDERS_KNOWN, ACTOR_HOLDING_DESCRIPTION_MAX_CHARS, ACTOR_HOLDING_MAX_ITEMS, ACTOR_MAX_AGE, ACTOR_MIN_AGE, ACTOR_NAME_MAX_CHARS, ACTOR_SETTING_MAX_CHARS, } from "./actor-bounds.js";
|
|
4
|
+
import { assetId } from "./asset-identity.js";
|
|
5
|
+
import { actorId, ASPECT_RATIOS } from "./skills.js";
|
|
5
6
|
/** Personal actors of an account. */
|
|
6
7
|
export { ACTOR_DEFAULT_QUALITY, ACTOR_QUALITIES_ACCEPTED, ACTOR_QUALITIES_KNOWN } from "./actor-qualities.js";
|
|
7
|
-
export { ACTOR_AGE_FLOOR, ACTOR_ASPECTS_KNOWN, ACTOR_DESCRIPTION_MAX_CHARS, ACTOR_GENDERS_ACCEPTED, ACTOR_GENDERS_KNOWN, ACTOR_MAX_AGE, ACTOR_MIN_AGE, ACTOR_NAME_MAX_CHARS, } from "./actor-bounds.js";
|
|
8
|
+
export { ACTOR_AGE_FLOOR, ACTOR_ASPECTS_KNOWN, ACTOR_DESCRIPTION_MAX_CHARS, ACTOR_GENDERS_ACCEPTED, ACTOR_GENDERS_KNOWN, ACTOR_HOLDING_DESCRIPTION_MAX_CHARS, ACTOR_HOLDING_MAX_ITEMS, ACTOR_MAX_AGE, ACTOR_MIN_AGE, ACTOR_NAME_MAX_CHARS, ACTOR_SETTING_MAX_CHARS, } from "./actor-bounds.js";
|
|
8
9
|
export const PERSONAL_ACTOR_ID_PREFIX = "actor_u_";
|
|
9
10
|
const PERSONAL_ACTOR_ID_BYTES = 16;
|
|
10
11
|
const BASE32_ALPHABET = "abcdefghijklmnopqrstuvwxyz234567";
|
|
@@ -46,23 +47,39 @@ export const ACTOR_SIZE_SET = {
|
|
|
46
47
|
};
|
|
47
48
|
const includesPortrait = (ratios) => ratios.includes(ACTOR_PORTRAIT_ASPECT);
|
|
48
49
|
const hasNoRepeats = (ratios) => new Set(ratios).size === ratios.length;
|
|
50
|
+
export const ACTOR_VIEW_FRAMINGS = ["wide"];
|
|
51
|
+
export const ACTOR_HANDS = ["left", "right"];
|
|
52
|
+
/** One held object: words, and optionally a picture of the object itself. */
|
|
53
|
+
const holdingItem = z.strictObject({
|
|
54
|
+
description: z.string().min(1).max(ACTOR_HOLDING_DESCRIPTION_MAX_CHARS).describe("The object, e.g. \"a white coffee mug\"."),
|
|
55
|
+
reference: z
|
|
56
|
+
.strictObject({ asset_id: assetId })
|
|
57
|
+
.optional()
|
|
58
|
+
.describe("A PNG or JPEG picture of the object: an image asset of this account (upload, URL import or a found picture, rights_confirmed)."),
|
|
59
|
+
hand: z.enum(ACTOR_HANDS).optional().describe("left | right; omitted lets the edit choose."),
|
|
60
|
+
});
|
|
49
61
|
/** Strict input fields without quality. Bounds come from actor-bounds.ts; read schemas do not use them. */
|
|
62
|
+
/** Words, gender and age are required without `from_actor_id` and refused with it (`checkActorSource`). */
|
|
50
63
|
const actorFieldShape = {
|
|
51
64
|
description: z
|
|
52
65
|
.string()
|
|
53
66
|
.min(1)
|
|
54
67
|
.max(ACTOR_DESCRIPTION_MAX_CHARS)
|
|
68
|
+
.optional()
|
|
55
69
|
.describe("Words describing a fictional adult: appearance, clothing, setting. Naming a real person or a likeness " +
|
|
56
|
-
"to one is refused before any charge (actor_prompt_refused)."),
|
|
70
|
+
"to one is refused before any charge (actor_prompt_refused). Required unless from_actor_id is given."),
|
|
57
71
|
gender: z
|
|
58
72
|
.enum(ACTOR_GENDERS_ACCEPTED)
|
|
59
|
-
.
|
|
73
|
+
.optional()
|
|
74
|
+
.describe(`${ACTOR_GENDERS_ACCEPTED.join(" | ")}. Fixes the actor's gender and the default voice of videos with this actor. ` +
|
|
75
|
+
"Required unless from_actor_id is given."),
|
|
60
76
|
approximate_age: z
|
|
61
77
|
.number()
|
|
62
78
|
.int()
|
|
63
79
|
.min(ACTOR_MIN_AGE)
|
|
64
80
|
.max(ACTOR_MAX_AGE)
|
|
65
|
-
.
|
|
81
|
+
.optional()
|
|
82
|
+
.describe(`Approximate age in years, ${ACTOR_MIN_AGE} to ${ACTOR_MAX_AGE}: actors are adults. Required unless from_actor_id is given.`),
|
|
66
83
|
name: z.string().min(1).max(ACTOR_NAME_MAX_CHARS).describe("Name shown in list_actors."),
|
|
67
84
|
aspect_ratios: z
|
|
68
85
|
.array(z.enum(ASPECT_RATIOS))
|
|
@@ -75,12 +92,65 @@ const actorFieldShape = {
|
|
|
75
92
|
.default([...ASPECT_RATIOS])
|
|
76
93
|
.describe(`Formats to create: ${ASPECT_RATIOS.join(" | ")}, always including ${ACTOR_PORTRAIT_ASPECT}. Omitted means all ` +
|
|
77
94
|
"three. Formats that fail the identity check are not charged and are named in warnings."),
|
|
95
|
+
from_actor_id: actorId
|
|
96
|
+
.optional()
|
|
97
|
+
.describe("Derive a new personal actor from this one (a library actor or your own): the same face, gender and age, " +
|
|
98
|
+
"with the view changed by framing, holding or setting. Omit description, gender and approximate_age."),
|
|
99
|
+
framing: z
|
|
100
|
+
.enum(ACTOR_VIEW_FRAMINGS)
|
|
101
|
+
.optional()
|
|
102
|
+
.describe("wide: the camera further back, the head lower with room above; make_ugc then renders it as a wide view."),
|
|
103
|
+
holding: z
|
|
104
|
+
.array(holdingItem)
|
|
105
|
+
.min(1)
|
|
106
|
+
.max(ACTOR_HOLDING_MAX_ITEMS)
|
|
107
|
+
.optional()
|
|
108
|
+
.describe(`Up to ${ACTOR_HOLDING_MAX_ITEMS} objects the presenter holds, one per hand.`),
|
|
109
|
+
setting: z
|
|
110
|
+
.string()
|
|
111
|
+
.min(1)
|
|
112
|
+
.max(ACTOR_SETTING_MAX_CHARS)
|
|
113
|
+
.optional()
|
|
114
|
+
.describe("The room or background to put the presenter in, in words."),
|
|
78
115
|
};
|
|
116
|
+
/** The fields of a view derived from an actor (#898). */
|
|
117
|
+
export const ACTOR_VIEW_FIELDS = ["from_actor_id", "framing", "holding", "setting"];
|
|
118
|
+
const ACTOR_VIEW_CHANGES = ["framing", "holding", "setting"];
|
|
119
|
+
const ACTOR_SOURCE_FIELDS = ["description", "gender", "approximate_age"];
|
|
120
|
+
/** A described actor needs its words, a derived one takes them from the source: neither is silently dropped (rule 3). */
|
|
121
|
+
function checkActorSource(input, ctx) {
|
|
122
|
+
const refuse = (field, message) => ctx.addIssue({ code: z.ZodIssueCode.custom, path: [field], message });
|
|
123
|
+
if (input.from_actor_id === undefined) {
|
|
124
|
+
for (const field of ACTOR_SOURCE_FIELDS) {
|
|
125
|
+
if (input[field] === undefined) {
|
|
126
|
+
refuse(field, `${field} is required: describe a fictional adult, or pass from_actor_id to derive a view of an existing actor`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
for (const field of ACTOR_VIEW_CHANGES) {
|
|
130
|
+
if (input[field] !== undefined) {
|
|
131
|
+
refuse(field, `${field} needs from_actor_id: create the actor first, then derive a view of it with from_actor_id`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
for (const field of ACTOR_SOURCE_FIELDS) {
|
|
137
|
+
if (input[field] !== undefined)
|
|
138
|
+
refuse(field, `${field} comes from the source actor with from_actor_id; omit it`);
|
|
139
|
+
}
|
|
140
|
+
if (ACTOR_VIEW_CHANGES.every((field) => input[field] === undefined)) {
|
|
141
|
+
refuse("from_actor_id", "from_actor_id needs a change: framing, holding or setting");
|
|
142
|
+
}
|
|
143
|
+
const hands = (input.holding ?? []).flatMap((item) => (item.hand === undefined ? [] : [item.hand]));
|
|
144
|
+
if (new Set(hands).size !== hands.length)
|
|
145
|
+
refuse("holding", "holding names the same hand twice: one object per hand");
|
|
146
|
+
}
|
|
79
147
|
function unknownFieldsRefusal(keys) {
|
|
80
148
|
if (keys.includes("image")) {
|
|
81
|
-
return "create_actor takes no image
|
|
149
|
+
return "create_actor takes no image of a person: describe a fictional adult in description, or derive a view of " +
|
|
150
|
+
"an existing actor with from_actor_id; a held object's picture goes in holding[].reference";
|
|
82
151
|
}
|
|
83
|
-
return `unknown field(s) ${keys.join(", ")}: create_actor accepts description, gender, approximate_age, name, quality,
|
|
152
|
+
return `unknown field(s) ${keys.join(", ")}: create_actor accepts description, gender, approximate_age, name, quality, ` +
|
|
153
|
+
"aspect_ratios, from_actor_id, framing, holding, setting";
|
|
84
154
|
}
|
|
85
155
|
/** The input for a given set of accepted qualities. */
|
|
86
156
|
export function createActorInputWith(accepted, defaultQuality) {
|
|
@@ -95,7 +165,7 @@ export function createActorInputWith(accepted, defaultQuality) {
|
|
|
95
165
|
"quote shows it before any charge."),
|
|
96
166
|
}, {
|
|
97
167
|
error: (issue) => (issue.code === "unrecognized_keys" ? unknownFieldsRefusal(issue.keys) : undefined),
|
|
98
|
-
});
|
|
168
|
+
}).superRefine(checkActorSource);
|
|
99
169
|
}
|
|
100
170
|
export const createActorInput = createActorInputWith(ACTOR_QUALITIES_ACCEPTED, ACTOR_DEFAULT_QUALITY);
|
|
101
171
|
/** Flat shape for MCP: the tool publishes the same schema the server checks. */
|
|
@@ -104,6 +174,13 @@ export const actorUnitCredits = z.object({
|
|
|
104
174
|
portrait: z.number().int().positive(),
|
|
105
175
|
variant: z.number().int().positive(),
|
|
106
176
|
});
|
|
177
|
+
/** Unit prices of a personal actor (owner's decision, clipwright#120). Admission copies them into the */
|
|
178
|
+
/** run's snapshot and settlement reads the snapshot, so a change here leaves old runs alone. ×2.5 over the S0 costs (owner, 29.10, */
|
|
179
|
+
/** #800): a portrait is a generate call ($0.0103 medium, $0.039 high), another format an edit ($0.024, $0.0581). */
|
|
180
|
+
export const ACTOR_UNIT_CREDITS = {
|
|
181
|
+
medium: { portrait: 4, variant: 8 },
|
|
182
|
+
high: { portrait: 12, variant: 18 },
|
|
183
|
+
};
|
|
107
184
|
/** Read schemas depend only on what could have been written: the known sets and the DB check. */
|
|
108
185
|
/** Intake bounds stay out, so narrowing intake never breaks old runs. */
|
|
109
186
|
const storedAspects = z.array(z.enum(ACTOR_ASPECTS_KNOWN)).min(1);
|
|
@@ -126,6 +203,24 @@ function sameFormats(left, right) {
|
|
|
126
203
|
const b = new Set(right);
|
|
127
204
|
return a.size === b.size && [...a].every((ratio) => b.has(ratio));
|
|
128
205
|
}
|
|
206
|
+
const sha256Hex = z.string().regex(/^[a-f0-9]{64}$/);
|
|
207
|
+
/** The source image admission resolved for `from_actor_id`: the worker reads these bytes, not a payload. */
|
|
208
|
+
export const storedActorSource = z.object({
|
|
209
|
+
actor_id: z.string().min(1),
|
|
210
|
+
scope: z.enum(ACTOR_SCOPES),
|
|
211
|
+
key: z.string().min(1),
|
|
212
|
+
sha256: sha256Hex,
|
|
213
|
+
width: z.number().int().positive(),
|
|
214
|
+
height: z.number().int().positive(),
|
|
215
|
+
framing: z.enum(["close", "wide"]),
|
|
216
|
+
});
|
|
217
|
+
/** A held object as admitted: a `reference` carries the asset row admission found. */
|
|
218
|
+
export const storedHoldingItem = z.object({
|
|
219
|
+
description: z.string().min(1),
|
|
220
|
+
hand: z.enum(ACTOR_HANDS).optional(),
|
|
221
|
+
reference: z.object({ asset_id: z.string().min(1) }).optional(),
|
|
222
|
+
picture: z.object({ asset_id: z.string().min(1), key: z.string().min(1), mime: z.enum(["image/png", "image/jpeg"]) }).optional(),
|
|
223
|
+
});
|
|
129
224
|
/** A stored run input. Quality and formats must match the snapshot, or generation would diverge */
|
|
130
225
|
/** from the charge, so such a run does not read (`run_input_unreadable`, zero credits). */
|
|
131
226
|
export const storedCreateActorInput = z
|
|
@@ -137,6 +232,11 @@ export const storedCreateActorInput = z
|
|
|
137
232
|
aspect_ratios: storedAspects,
|
|
138
233
|
quality: z.enum(ACTOR_QUALITIES_KNOWN),
|
|
139
234
|
pricing_snapshot: actorPricingSnapshot,
|
|
235
|
+
from_actor_id: z.string().min(1).optional(),
|
|
236
|
+
source_actor: storedActorSource.optional(),
|
|
237
|
+
framing: z.enum(ACTOR_VIEW_FRAMINGS).optional(),
|
|
238
|
+
holding: z.array(storedHoldingItem).optional(),
|
|
239
|
+
setting: z.string().min(1).optional(),
|
|
140
240
|
})
|
|
141
241
|
.refine((input) => input.quality === input.pricing_snapshot.quality, {
|
|
142
242
|
error: "stored quality differs from pricing_snapshot.quality",
|
|
@@ -145,6 +245,16 @@ export const storedCreateActorInput = z
|
|
|
145
245
|
.refine((input) => sameFormats(input.aspect_ratios, input.pricing_snapshot.requested_aspects), {
|
|
146
246
|
error: "stored aspect_ratios differ from pricing_snapshot.requested_aspects",
|
|
147
247
|
path: ["aspect_ratios"],
|
|
248
|
+
})
|
|
249
|
+
.refine((input) => (input.from_actor_id === undefined) === (input.source_actor === undefined)
|
|
250
|
+
&& (input.source_actor === undefined || input.source_actor.actor_id === input.from_actor_id), {
|
|
251
|
+
error: "stored from_actor_id and source_actor disagree",
|
|
252
|
+
path: ["source_actor"],
|
|
253
|
+
})
|
|
254
|
+
.refine((input) => (input.holding ?? []).every((item) => (item.reference === undefined) === (item.picture === undefined)
|
|
255
|
+
&& (item.picture === undefined || item.picture.asset_id === item.reference?.asset_id)), {
|
|
256
|
+
error: "a stored holding reference has no admitted picture",
|
|
257
|
+
path: ["holding"],
|
|
148
258
|
});
|
|
149
259
|
export const createActorQuote = z.object({
|
|
150
260
|
skill: z.literal("create_actor"),
|
|
@@ -178,7 +288,23 @@ export const CREATE_ACTOR_FIELD_DISPOSITIONS = {
|
|
|
178
288
|
name: { kind: "implemented", provenBy: "listing" },
|
|
179
289
|
quality: { kind: "implemented", provenBy: "egress" },
|
|
180
290
|
aspect_ratios: { kind: "implemented", provenBy: "egress" },
|
|
291
|
+
from_actor_id: { kind: "implemented", provenBy: "egress" },
|
|
292
|
+
framing: { kind: "implemented", provenBy: "egress" },
|
|
293
|
+
holding: { kind: "implemented", provenBy: "egress" },
|
|
294
|
+
setting: { kind: "implemented", provenBy: "egress" },
|
|
181
295
|
};
|
|
296
|
+
export const ACTOR_VIEWS_DISABLED_MESSAGE = "is switched off on this deployment: deriving an actor from an actor is not available; create an actor from a description instead";
|
|
297
|
+
/** The registry with `CLIPWRIGHT_ACTOR_VIEWS` applied: switched off, the view fields are refused, not ignored. */
|
|
298
|
+
export function createActorDispositions(viewsEnabled) {
|
|
299
|
+
if (viewsEnabled)
|
|
300
|
+
return CREATE_ACTOR_FIELD_DISPOSITIONS;
|
|
301
|
+
const rejected = (field) => ({ kind: "rejected", message: `${field} ${ACTOR_VIEWS_DISABLED_MESSAGE}` });
|
|
302
|
+
return { ...CREATE_ACTOR_FIELD_DISPOSITIONS, ...Object.fromEntries(ACTOR_VIEW_FIELDS.map((field) => [field, rejected(field)])) };
|
|
303
|
+
}
|
|
304
|
+
/** Present fields whose disposition is `rejected`, in registry order, for `rejectedFieldBody`. */
|
|
305
|
+
export function createActorRejectedFields(input, dispositions) {
|
|
306
|
+
return Object.entries(dispositions).flatMap(([field, disposition]) => disposition.kind === "rejected" && input[field] !== undefined ? [{ field, message: disposition.message }] : []);
|
|
307
|
+
}
|
|
182
308
|
/** Admission warnings come only from the registry; written to `runs.warnings`, not recomputed on read. */
|
|
183
309
|
export function createActorAdmissionWarnings(input, dispositions = CREATE_ACTOR_FIELD_DISPOSITIONS) {
|
|
184
310
|
return Object.entries(dispositions).flatMap(([field, disposition]) => disposition.kind === "warned" && input[field] !== undefined ? [disposition.warning] : []);
|
|
@@ -195,6 +321,9 @@ export const CREATE_ACTOR_RUN_ERRORS = {
|
|
|
195
321
|
actor_generation_disabled: "actor generation is disabled right now; no actor was created and nothing was charged",
|
|
196
322
|
actor_run_interrupted: "the run stopped before it finished; no actor was created and nothing was charged",
|
|
197
323
|
actor_spend_refused: "our spend guard refused the paid call; no actor was created and nothing was charged. Retry later",
|
|
324
|
+
actor_identity_not_kept: "the edited portrait did not keep the source actor's face; no actor was created and nothing was charged",
|
|
325
|
+
actor_source_unreadable: "the source actor or a held object's picture could not be read; no actor was created and nothing was charged",
|
|
326
|
+
actor_views_disabled: "deriving an actor from an actor is disabled right now; no actor was created and nothing was charged",
|
|
198
327
|
};
|
|
199
328
|
export const CREATE_ACTOR_RUN_ERROR_CODES = Object.keys(CREATE_ACTOR_RUN_ERRORS);
|
|
200
329
|
export function createActorRunError(code) {
|
|
@@ -218,5 +347,8 @@ export const CREATE_ACTOR_DESCRIPTION = "Create a personal actor for this accoun
|
|
|
218
347
|
"one face, plus the other requested formats edited from it. Returns a run_id immediately; poll get_run until " +
|
|
219
348
|
"'succeeded' (created_actor.actor_id, then pass it as actor_id to make_ugc) or 'failed'. Each published image is " +
|
|
220
349
|
"charged at the price quote shows; refused descriptions and unusable portraits cost nothing. When generation is " +
|
|
221
|
-
"switched off the call fails with actor_generation_disabled."
|
|
350
|
+
"switched off the call fails with actor_generation_disabled. With from_actor_id it derives a new personal actor " +
|
|
351
|
+
"from a library or own actor: the same face (checked; a mismatch costs nothing), with framing wide, objects in " +
|
|
352
|
+
"holding or a new setting. A held object's picture is an image asset (upload, URL import or a found picture, " +
|
|
353
|
+
"rights_confirmed).";
|
|
222
354
|
//# sourceMappingURL=account-actors.js.map
|