@nodaro/shared 1.5.0 → 1.7.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.
@@ -1077,6 +1077,9 @@ export const DURATION_PRICED_PROVIDERS = new Set([
1077
1077
  "seedance-2-fast",
1078
1078
  "seedance-2-mini",
1079
1079
  "grok-imagine-video-1.5",
1080
+ "happyhorse",
1081
+ "happyhorse-i2v",
1082
+ "happyhorse-ref2v",
1080
1083
  ])
1081
1084
 
1082
1085
  /**
@@ -1243,6 +1246,13 @@ export const RESOLUTION_DURATION_PRICING: Record<string, readonly string[]> = {
1243
1246
  // seedance-2-extend always uses a video ref, so pricing has no -ref
1244
1247
  // dimension — duration tier + ":res" only (rates = seedance-2 -ref + stitch).
1245
1248
  "seedance-2-extend": ["480p", "720p", "1080p"],
1249
+ // HappyHorse 1.1 — per-second billing at two published resolution rates
1250
+ // (kie.ai/happyhorse-1-1: 22.5 cr/s @720p, 29 cr/s @1080p, uniform across
1251
+ // t2v/i2v/ref2v). 720p first = billing default; the KIE-side default is
1252
+ // pinned to 720p via extraParams in backend kie/models.ts so render matches.
1253
+ "happyhorse": ["720p", "1080p"],
1254
+ "happyhorse-i2v": ["720p", "1080p"],
1255
+ "happyhorse-ref2v": ["720p", "1080p"],
1246
1256
  }
1247
1257
 
1248
1258
  /**
@@ -1489,6 +1499,13 @@ export const VIDEO_VARIABLE_PRICING: Record<string, "duration" | "duration+audio
1489
1499
  "grok-imagine-video-1.5": "duration+resolution",
1490
1500
  }
1491
1501
 
1502
+ /** HappyHorse 1.1 per-second tiers — one per allowed duration (3–15s), shared
1503
+ * by all three modes (t2v/i2v/ref2v) which bill at identical published rates. */
1504
+ const HAPPYHORSE_DURATION_TIERS: Array<{ maxSeconds: number; suffix: string }> = Array.from(
1505
+ { length: 13 },
1506
+ (_, i) => ({ maxSeconds: i + 3, suffix: `${i + 3}s` }),
1507
+ )
1508
+
1492
1509
  /**
1493
1510
  * Duration tier breakpoints for variable-priced video models.
1494
1511
  * Maps provider → array of { maxSeconds, suffix } in ascending order.
@@ -1588,6 +1605,14 @@ export const VIDEO_DURATION_TIERS: Record<string, Array<{ maxSeconds: number; su
1588
1605
  { maxSeconds: 14, suffix: "14s" },
1589
1606
  { maxSeconds: 15, suffix: "15s" },
1590
1607
  ],
1608
+ // HappyHorse 1.1 (t2v / i2v / ref2v) — true per-second billing (KIE 22.5 cr/s
1609
+ // @720p, 29 cr/s @1080p, published on kie.ai/happyhorse-1-1). One tier per
1610
+ // allowed second (3–15s) so the composite identifier maps 1:1 to the seeded
1611
+ // price, combined with RESOLUTION_DURATION_PRICING for the ":720p"/":1080p"
1612
+ // suffix (e.g. "happyhorse-i2v:5s:720p").
1613
+ "happyhorse": HAPPYHORSE_DURATION_TIERS,
1614
+ "happyhorse-i2v": HAPPYHORSE_DURATION_TIERS,
1615
+ "happyhorse-ref2v": HAPPYHORSE_DURATION_TIERS,
1591
1616
  }
1592
1617
 
1593
1618
  /**
@@ -148,7 +148,7 @@ export const StageAwaitingSubGateEventSchema = z.object({
148
148
  pipelineId: z.string().uuid(),
149
149
  stageName: z.enum(["animate_audio_edit", "scene_images"]),
150
150
  subGate: SubGateNameSchema,
151
- payload: z.record(z.unknown()).optional(),
151
+ payload: z.record(z.string(), z.unknown()).optional(),
152
152
  })
153
153
  export type StageAwaitingSubGateEvent = z.infer<typeof StageAwaitingSubGateEventSchema>
154
154
 
@@ -1,4 +1,4 @@
1
- import { z, type ZodType, type ZodTypeDef } from "zod"
1
+ import { z, type ZodType } from "zod"
2
2
  // Reuse the canonical `OutputType` from presentation-utils so a single union
3
3
  // is the source of truth across the package. Re-exporting it here would
4
4
  // collide with the explicit named re-export in `index.ts`.
@@ -13,7 +13,7 @@ export type ReduceStrategy<TConfig = unknown> = {
13
13
  readonly label: string
14
14
  readonly description: string
15
15
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
16
- readonly configSchema: ZodType<TConfig, ZodTypeDef, any>
16
+ readonly configSchema: ZodType<TConfig, any>
17
17
  readonly defaultConfig: TConfig
18
18
  readonly outputType: OutputType
19
19
  readonly creditCostKey: string
@@ -9,9 +9,9 @@ import { DEFAULT_LABEL_BY_SOURCE, type ReferenceSource } from "./types.js"
9
9
  * value (guarded by reference-roles.test.ts).
10
10
  */
11
11
  export const REFERENCE_ROLE_PRESETS: Record<ReferenceSource, readonly string[]> = {
12
- "wired-character": ["person", "face", "clothes", "hair", "pose", "expression", "style"],
12
+ "wired-character": ["ref-only", "person", "face", "clothes", "hair", "pose", "expression", "style"],
13
13
  "wired-face": ["face", "person", "expression", "style"],
14
- "wired-location": ["background", "atmosphere", "as-is", "empty background", "layout", "lighting", "style"],
14
+ "wired-location": ["ref-only", "background", "atmosphere", "as-is", "empty background", "layout", "lighting", "style"],
15
15
  "wired-object": ["object", "shape", "material", "color", "texture", "style"],
16
16
  "wired-creature": ["creature", "anatomy", "markings", "pose", "color", "style"],
17
17
  "wired-image": ["object", "person", "face", "clothes", "background", "style", "pose", "texture"],
@@ -35,6 +35,10 @@ export function roleToPhrase(role: string, binding: string): string {
35
35
  const r = role.trim()
36
36
  if (!r) return binding
37
37
  switch (r) {
38
+ case "ref-only":
39
+ // Bare reference pointer — no descriptive phrase. The label-less/default
40
+ // state for media refs; an explicit pick for character/location assets.
41
+ return binding
38
42
  case "as-is":
39
43
  return `${binding}, used as-is`
40
44
  case "empty background":
@@ -89,7 +89,7 @@ export const ShotSpecSchema = z.object({
89
89
  camera_path_directive: z
90
90
  .object({
91
91
  path_kind: z.enum(["orbit", "dolly", "crane", "arc", "reveal"]),
92
- parameters: z.record(z.unknown()).optional(),
92
+ parameters: z.record(z.string(), z.unknown()).optional(),
93
93
  })
94
94
  .optional(),
95
95
 
package/src/types.ts CHANGED
@@ -82,6 +82,13 @@ export interface ConnectedReference {
82
82
  readonly characterSlug?: string
83
83
  /** Variant slug (e.g. "smile"). undefined = canonical/default. */
84
84
  readonly variantSlug?: string
85
+ /**
86
+ * Which character asset bucket this entry came from ("boards", "sheets",
87
+ * "expressions", …); undefined = the canonical portrait entry. DISPLAY
88
+ * metadata only — menus use it to rank rows (boards first) via
89
+ * `sortCharacterEntriesForDisplay`; it never affects payload numbering.
90
+ */
91
+ readonly bucket?: string
85
92
  /** Character's canonical_description. Set on every entry from the same character (used for dedup). */
86
93
  readonly characterCanonicalDescription?: string | null
87
94
  /**
@@ -205,8 +212,11 @@ export interface ConnectedReference {
205
212
 
206
213
  /** Default label per source — used by `@` autocomplete and inventory fallback. */
207
214
  export const DEFAULT_LABEL_BY_SOURCE: Record<ReferenceSource, string> = {
208
- "manual": "object",
209
- "wired-image": "object",
215
+ // Media references default to "ref-only" — the empty label, i.e. a bare
216
+ // {image:N} token that injects only "reference image A" (image) / "@image_N"
217
+ // (video) with no descriptive role phrase. Pick a role on the pill to change.
218
+ "manual": "",
219
+ "wired-image": "",
210
220
  "wired-character": "person",
211
221
  "wired-face": "face",
212
222
  "wired-object": "object",