Documentation
¶
Overview ¶
Dry run (R-GLOBAL-5): price a generation without performing it. The commands that spend — cover, portrait, voice gen, music gen, cards gen — each expose this as `--dry-run`, so an operator (or an agent driving the CLI, or an MCP client that cannot answer an interactive prompt) can ask what a request would cost before committing to it. That is the workable form of R-MCP-3's confirm posture: the `reel make` guard is an interactive prompt, which cannot function over MCP.
Package gencmd holds workspace-aware take generation for the authoring loop: generate N candidate takes from a workspace's storyboard into <kind>/takes/, to be auditioned and selected (internal/takes). Generation is finite and bounded (R-GLOBAL-11) and every provider call is context-timed (R-GLOBAL-12).
Index ¶
- Variables
- func CardTakes(ctx context.Context, p *props.Props, slug string, card, n int, ...) error
- func DictLocators(dictID string) []provider.DictLocator
- func EmitDryRun(command string, dr DryRun) error
- func GenerateInto(ctx context.Context, p *props.Props, fs afero.Fs, req Request) ([]string, error)
- func MusicTakes(ctx context.Context, p *props.Props, slug string, n int, themeKw string, ...) error
- func ParseLines(s string) ([]int, error)
- func ResolveQuota(cfg config.Reader) (provider.QuotaReporter, error)
- func VOTakes(ctx context.Context, p *props.Props, slug string, line, n int, ...) error
- func VOTakesLines(ctx context.Context, p *props.Props, slug string, lines []int, n int, ...) error
- type DryRun
- type Request
- type Target
Constants ¶
This section is empty.
Variables ¶
var ErrNoQuota = errors.NewSentinel("keyrx.no_quota", "the configured voice provider does not report a character quota")
ErrNoQuota is returned when the configured voice provider does not report a character quota (an optional capability — spec 0016).
Functions ¶
func CardTakes ¶
func CardTakes(ctx context.Context, p *props.Props, slug string, card, n int, themeKw, avatarName string, force bool) error
CardTakes generates n candidate illustrations per target card into cards/takes/. card == 0 targets every overlay card that has a scene; otherwise just that 1-based card. Each card's prompt is the reel theme's illustration style + the card scene + the wordless hardening.
func DictLocators ¶ added in v0.4.0
func DictLocators(dictID string) []provider.DictLocator
DictLocators turns a theme/voice pronunciation-dictionary id into request locators (the latest version resolves at run time); empty ⇒ nil ⇒ omitted.
func EmitDryRun ¶ added in v0.12.0
EmitDryRun reports a preview on stdout — the estimate in text, or the whole DryRun as structured data under `--output json` (R-GLOBAL-3), which is the form an MCP client reads (R-MCP-4).
func GenerateInto ¶
GenerateInto runs one bounded, timed generation, writing Count candidate takes into the request's slot on fs and returning their paths (fs-relative). It is the single FS-explicit core the studio drives for every media kind — image (card / cover / portrait) and audio (VO / music) — on its active worktree (which may be an in-memory remote). Prompt/voice + take layout are shared with the CLI commands, so studio and CLI takes are identical.
func MusicTakes ¶
func MusicTakes(ctx context.Context, p *props.Props, slug string, n int, themeKw string, lengthMS int, force bool) error
MusicTakes generates n candidate beds into music/takes/ (the CLI wrapper). lengthMS sizes the bed: 0 means "default to the VO-driven total" (the bed should cover the whole reel); a positive value is an explicit override (--length).
func ParseLines ¶ added in v0.4.0
ParseLines parses a `--lines` value — a comma list ("3,5,7"), a range ("3-6"), or a mix ("1,3-5,8") of 1-based storyboard lines — into a sorted, deduped list (spec 0023 §3.1).
func ResolveQuota ¶ added in v0.8.0
func ResolveQuota(cfg config.Reader) (provider.QuotaReporter, error)
ResolveQuota resolves the configured voice provider and its optional quota capability, returning ErrNoQuota when the provider tracks none. Shared by the `voice quota` CLI and the studio quota widget so both resolve identically.
func VOTakes ¶
func VOTakes(ctx context.Context, p *props.Props, slug string, line, n int, themeKw, model string, allowUnknown, force bool) error
VOTakes generates n VO takes for storyboard line (1-based) into vo/takes/ (the CLI wrapper over the FS-explicit GenerateInto, on p.FS).
func VOTakesLines ¶ added in v0.4.0
func VOTakesLines(ctx context.Context, p *props.Props, slug string, lines []int, n int, themeKw, model string, allowUnknown, force bool) error
VOTakesLines re-rolls exactly the named lines — n fresh candidate takes each — leaving every other line's takes and selections untouched (R-GEN-36). Each line resolves its own per-card voice overrides, as the single-line path does.
Types ¶
type DryRun ¶ added in v0.12.0
type DryRun struct {
Target string `json:"target"`
Count int `json:"count"`
Cost spend.Cost `json:"cost"`
// OverCap names the spend-guard axis the estimate crosses ("amount" |
// "characters"), empty when it stays under both. The guard is not applied here —
// a dry run spends nothing, so there is nothing to gate.
OverCap string `json:"over_cap,omitempty"`
// Noun is what one unit of the output is called in the TEXT form, where "take"
// would be wrong — a storyboard draft is a board, not a candidate to choose
// between. Empty means "take". Off the wire deliberately: it is prose, and the
// JSON shape is a contract an MCP client reads.
Noun string `json:"-"`
// Uncached suppresses the "served from the cache without spending" line, which
// is true of every media generation (R-GLOBAL-9) and false of a storyboard
// draft — there is no content cache on the chat path, so a re-run pays again.
// Someone acts on that sentence, so it must not be said where it is untrue.
Uncached bool `json:"-"`
}
DryRun is what a generation would do and what it would cost. Count is the number of billable units the run would produce — takes for a single target, takes × cards for a whole-board card run — so it matches Cost.Count rather than the request's per-item `--takes`.
The estimate is an upper bound, not a prediction: an unchanged request is served from the content cache without spending (R-GLOBAL-9), and a real run may therefore cost nothing at all.
func Preview ¶ added in v0.12.0
Preview prices req without calling a provider and without writing anything. It reads the storyboard (to size VO narration and count the cards a whole-board run would generate) and the config (for rates and the cap), which is why it takes the same fs the real run would use.
func PreviewInWorkspace ¶ added in v0.12.0
func PreviewInWorkspace(ctx context.Context, p *props.Props, slug string, req Request) (DryRun, error)
PreviewInWorkspace prices a workspace-scoped generation (cards / VO / music) from its slug, mirroring CardTakes/VOTakes/MusicTakes so the slug→dir resolution stays in one place. Cover and portrait are not workspace-scoped and call Preview directly.
type Request ¶
type Request struct {
Target Target
Dir string // workspace dir on the target fs
Card int // TargetCard: 1-based card index
Line int // TargetVO: 1-based storyboard line
Scene string // TargetCard/TargetCover: the illustration scene
Theme string // theme keyword, resolved against the target's theme type
// Aspect overrides the generated image's frame shape (TargetCover): a reel
// cover follows the reel's aspect (0029 §9 note 27), not the article theme's.
Aspect string
Refs []provider.RefImage // TargetPortrait: reference photos (image-to-image)
// Avatars is the card's cast (TargetCard): registered avatar names whose likeness
// is directed into the scene via image-to-image (spec 0034 D4). Empty = a plain
// text-to-image card in the theme style (the pre-avatar behaviour).
Avatars []string
Count int // candidate takes
// LengthMS is the requested music bed length (TargetMusic): 0 = default to the
// VO-driven total, positive = explicit override.
LengthMS int
// Model overrides the TTS model (TargetVO); empty ⇒ theme/default. AllowUnknown
// accepts a Model outside the allowlist (spec 0022 B).
Model string
AllowUnknown bool
// Force bypasses the content cache (R-GEN-8): regenerate + refresh the cached set
// even when the request is unchanged. Maps to the CLI `--force`.
Force bool
}
Request is a provider-neutral studio generation request: keryx's intent (what to make, under which theme), not a vendor payload.