@laplace.live/persona-sdk 1.24.0 → 1.25.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.
Files changed (44) hide show
  1. package/README.md +10 -10
  2. package/dist/client/client.js +5 -6
  3. package/dist/client/legacy-names.d.ts +2 -0
  4. package/dist/client/{legacy-kinds.js → legacy-names.js} +12 -3
  5. package/dist/client/node.d.ts +13 -0
  6. package/dist/client/node.js +29 -0
  7. package/dist/client/scene-hotkeys.d.ts +16 -0
  8. package/dist/client/scene-hotkeys.js +17 -0
  9. package/dist/index.d.ts +3 -0
  10. package/dist/index.js +3 -0
  11. package/dist/values/bindings.d.ts +40 -15
  12. package/dist/values/controller.d.ts +9 -6
  13. package/dist/values/edit-history.d.ts +4 -0
  14. package/dist/values/edit-history.js +14 -7
  15. package/dist/values/effect-schema.d.ts +26 -0
  16. package/dist/values/effect-schema.js +76 -91
  17. package/dist/values/hotkey-targets.d.ts +10 -3
  18. package/dist/values/hotkey-targets.js +20 -0
  19. package/dist/values/hotkeys.d.ts +9 -1
  20. package/dist/values/hotkeys.js +11 -0
  21. package/dist/values/labels.js +1 -0
  22. package/dist/values/limits.d.ts +96 -8
  23. package/dist/values/limits.js +109 -1
  24. package/dist/values/lipsync.d.ts +7 -8
  25. package/dist/values/locale.d.ts +4 -1
  26. package/dist/values/locale.js +4 -0
  27. package/dist/values/model-movement.d.ts +19 -4
  28. package/dist/values/model-movement.js +17 -4
  29. package/dist/values/volumetric-lighting.d.ts +1 -1
  30. package/dist/values/volumetric-lighting.js +1 -1
  31. package/dist/wire/envelope.js +6 -3
  32. package/dist/wire/methods.d.ts +16 -17
  33. package/dist/wire/protocol.d.ts +2 -0
  34. package/dist/wire/protocol.js +4 -0
  35. package/dist/wire/schemas/fields.d.ts +8 -0
  36. package/dist/wire/schemas/fields.js +1 -0
  37. package/dist/wire/schemas/requests.d.ts +2 -2
  38. package/dist/wire/schemas/requests.js +70 -20
  39. package/dist/wire/schemas/settings.d.ts +3 -3
  40. package/dist/wire/schemas/settings.js +3 -3
  41. package/dist/wire/types.d.ts +68 -115
  42. package/dist/wire/types.js +68 -9
  43. package/package.json +2 -2
  44. package/dist/client/legacy-kinds.d.ts +0 -2
@@ -2,7 +2,7 @@ import * as z from 'zod';
2
2
  import { CONTROLLER_DEAD_ZONE_MAX } from "../../values/controller.js";
3
3
  import { isRecord } from "../../values/guards.js";
4
4
  import { ITEM_TRANSITION_STYLES, LEGACY_DITHER_STYLE } from "../../values/item-transition.js";
5
- import { OBJECT_ADD_MANY_MAX, SCENE_COLOR_RE, SPEECH_URL_MAX_LENGTH, STAGE_CAPTURE_EDGE_MAX, STAGE_CAPTURE_EDGE_MIN, STORAGE_KEY_MAX_LENGTH, STORAGE_VALUE_MAX_LENGTH, } from "../../values/limits.js";
5
+ import { OBJECT_ADD_MANY_MAX, SCENE_COLOR_RE, SESSION_NAME_MAX_LENGTH, SPEECH_URL_MAX_LENGTH, STAGE_CAPTURE_EDGE_MAX, STAGE_CAPTURE_EDGE_MIN, STORAGE_KEY_MAX_LENGTH, STORAGE_VALUE_MAX_LENGTH, } from "../../values/limits.js";
6
6
  import { LIP_SYNC_CALIBRATION_ACTIONS, LIP_SYNC_MODES, LIP_SYNC_PHONEMES, } from "../../values/lipsync.js";
7
7
  import { SCENE_TRANSITION_DURATION_MAX_MS, SCENE_TRANSITION_DURATION_MIN_MS, SCENE_TRANSITION_FADE_DEFAULT_MS, SCENE_TRANSITION_SWITCH_POINT_MAX, SCENE_TRANSITION_SWITCH_POINT_MIN, SCENE_TRANSITION_TYPES, } from "../../values/scene-transition.js";
8
8
  import { ASSET_KINDS, INJECT_TARGET_TYPES, POSE_SOURCE_IDS, TRACKING_SOURCE_IDS, TRACKING_SOURCE_KINDS, } from "../types.js";
@@ -68,20 +68,35 @@ const objectAdd = z.object({
68
68
  place3d: z.custom(isRecord, 'place3d must be an object').optional(),
69
69
  });
70
70
  const stageVector = z.object({ x: z.number(), y: z.number(), z: z.number() });
71
+ // Each object schema `satisfies Fields<…>` of its request, so an optional field the interface gains
72
+ // fails to compile here instead of being stripped before the executor sees it.
71
73
  export const requestSchemas = {
72
74
  'lipSync.state': z.object({}),
73
75
  'lipSync.configure': lipSyncPatch,
74
76
  'lipSync.restart': z.object({}),
75
77
  'lipSync.calibrate': lipSyncCalibration,
76
- 'instance.setLipSync': z.object({ instanceId: nonEmpty.optional(), mode: z.enum(LIP_SYNC_MODES) }),
77
- 'registry.thumbnail': z.object({ kind: z.enum(['model', 'asset']), id: nonEmpty }),
78
- 'controller.rename': z.object({ slot: z.number().int().positive(), name: z.string() }),
78
+ 'instance.setLipSync': z.object({
79
+ instanceId: nonEmpty.optional(),
80
+ mode: z.enum(LIP_SYNC_MODES),
81
+ }),
82
+ 'registry.thumbnail': z.object({
83
+ kind: z.enum(['model', 'asset']),
84
+ id: nonEmpty,
85
+ }),
86
+ 'controller.rename': z.object({
87
+ slot: z.number().int().positive(),
88
+ name: z.string(),
89
+ }),
79
90
  'controller.setDeadZone': z.object({
80
91
  slot: z.number().int().positive(),
81
92
  deadZone: z.number().min(0).max(CONTROLLER_DEAD_ZONE_MAX),
82
93
  }),
83
- 'controller.remove': z.object({ slot: z.number().int().positive() }),
84
- 'controller.assign': z.object({ slot: z.number().int().positive().nullable() }),
94
+ 'controller.remove': z.object({
95
+ slot: z.number().int().positive(),
96
+ }),
97
+ 'controller.assign': z.object({
98
+ slot: z.number().int().positive().nullable(),
99
+ }),
85
100
  'scene.get': z.object({ sceneId: nonEmpty.optional() }),
86
101
  'scene.activate': z.object({ sceneId: nonEmpty }),
87
102
  'scene.duplicate': z.object({ sceneId: nonEmpty }),
@@ -90,24 +105,44 @@ export const requestSchemas = {
90
105
  'scene.setLightFollowCamera': z.object({
91
106
  lightId: nonEmpty,
92
107
  followCamera: z.boolean(),
93
- options: z.object({ position: z.boolean(), rotation: z.boolean(), distance: z.boolean() }).partial().optional(),
108
+ options: z
109
+ .object({
110
+ position: z.boolean(),
111
+ rotation: z.boolean(),
112
+ distance: z.boolean(),
113
+ })
114
+ .partial()
115
+ .optional(),
94
116
  }),
95
117
  'instance.add': z.object({ modelId: nonEmpty }),
96
- 'instance.setModel': z.object({ instanceId: nonEmpty, modelId: nonEmpty }),
118
+ 'instance.setModel': z.object({
119
+ instanceId: nonEmpty,
120
+ modelId: nonEmpty,
121
+ }),
97
122
  'object.add': objectAdd,
98
- 'object.addMany': z.object({ objects: z.array(objectAdd).min(1).max(OBJECT_ADD_MANY_MAX) }),
123
+ 'object.addMany': z.object({
124
+ objects: z.array(objectAdd).min(1).max(OBJECT_ADD_MANY_MAX),
125
+ }),
99
126
  'object.setContent': z.object({
100
127
  instanceId: nonEmpty,
101
128
  content: z.custom(isRecord, 'content must be an object'),
102
129
  }),
103
- 'expression.getPersistence': z.object({ modelId: nonEmpty.optional() }),
104
- 'expression.setPersistence': z.object({ modelId: nonEmpty.optional(), enabled: z.boolean() }),
130
+ 'expression.getPersistence': z.object({
131
+ modelId: nonEmpty.optional(),
132
+ }),
133
+ 'expression.setPersistence': z.object({
134
+ modelId: nonEmpty.optional(),
135
+ enabled: z.boolean(),
136
+ }),
105
137
  'hotkey.list': z.object({ modelId: nonEmpty.optional() }),
106
138
  'hotkey.set': z.object({
107
139
  modelId: nonEmpty.optional(),
108
140
  config: z.custom(isRecord, 'config must be a hotkey config'),
109
141
  }),
110
- 'hotkey.trigger': z.object({ hotkeyId: nonEmpty, modelId: nonEmpty.optional() }),
142
+ 'hotkey.trigger': z.object({
143
+ hotkeyId: nonEmpty,
144
+ modelId: nonEmpty.optional(),
145
+ }),
111
146
  'automation.run': z.object({ automationId: nonEmpty }),
112
147
  'tracking.addSource': z.object({
113
148
  // Straight off the kind registry, for the same reason as ASSET_KINDS below: a schema
@@ -128,7 +163,9 @@ export const requestSchemas = {
128
163
  }),
129
164
  'tracking.removeSource': z.object({ id: nonEmpty }),
130
165
  'model.register': z.object({ path: nonEmpty }),
131
- 'model.getMovement': z.object({ modelId: nonEmpty.optional() }),
166
+ 'model.getMovement': z.object({
167
+ modelId: nonEmpty.optional(),
168
+ }),
132
169
  // Healed by the host like the desktop editor's own edits, so only the shape is checked here.
133
170
  'model.setMovement': z.object({
134
171
  modelId: nonEmpty.optional(),
@@ -136,15 +173,20 @@ export const requestSchemas = {
136
173
  }),
137
174
  // Straight off ASSET_KINDS: a kind added there has to reach the wire gate too, or
138
175
  // `want` answers invalid-params for a kind the registry already knows how to take.
139
- 'asset.register': z.object({ path: nonEmpty, want: z.enum(ASSET_KINDS).optional() }),
176
+ 'asset.register': z.object({
177
+ path: nonEmpty,
178
+ want: z.enum(ASSET_KINDS).optional(),
179
+ }),
140
180
  'settings.patch': z.object({ settings: SettingsPatchSchema }),
141
181
  'tracking.setEnabled': z.object({ enabled: z.boolean() }),
142
- 'tracking.setSource': z.object({ source: z.enum(TRACKING_SOURCE_IDS) }),
182
+ 'tracking.setSource': z.object({
183
+ source: z.enum(TRACKING_SOURCE_IDS),
184
+ }),
143
185
  'pose.setEnabled': z.object({ enabled: z.boolean() }),
144
186
  'pose.setSource': z.object({ source: z.enum(POSE_SOURCE_IDS) }),
145
187
  'pose.setPort': z.object({ port: PortSchema }),
146
188
  'session.identify': z.object({
147
- name: z.string().trim().min(1).max(64),
189
+ name: z.string().trim().min(1).max(SESSION_NAME_MAX_LENGTH),
148
190
  version: z.string().max(32).optional(),
149
191
  developer: z.string().max(64).optional(),
150
192
  }),
@@ -181,10 +223,18 @@ export const requestSchemas = {
181
223
  'stage.capture': z.object({
182
224
  maxEdge: z.number().int().min(STAGE_CAPTURE_EDGE_MIN).max(STAGE_CAPTURE_EDGE_MAX).optional(),
183
225
  }),
184
- 'events.subscribe': z.object({ events: z.array(lenientEventNameSchema).min(1) }),
185
- 'events.unsubscribe': z.object({ events: z.array(lenientEventNameSchema).optional() }),
186
- 'param.inject': z.object({ entries: z.array(InjectEntrySchema).min(1) }),
187
- 'param.release': z.object({ targets: z.array(InjectTargetSchema).optional() }),
226
+ 'events.subscribe': z.object({
227
+ events: z.array(lenientEventNameSchema).min(1),
228
+ }),
229
+ 'events.unsubscribe': z.object({
230
+ events: z.array(lenientEventNameSchema).optional(),
231
+ }),
232
+ 'param.inject': z.object({
233
+ entries: z.array(InjectEntrySchema).min(1),
234
+ }),
235
+ 'param.release': z.object({
236
+ targets: z.array(InjectTargetSchema).optional(),
237
+ }),
188
238
  };
189
239
  /**
190
240
  * Validate one request's params against its method schema. Methods without a
@@ -56,12 +56,12 @@ export declare const MediaPipeConfigSchema: z.ZodObject<{
56
56
  export declare const TrackingSourceConfigSchema: z.ZodObject<{
57
57
  id: z.ZodString;
58
58
  kind: z.ZodEnum<{
59
+ mediapipe: "mediapipe";
59
60
  "persona-ios": "persona-ios";
60
61
  ifacialmocap: "ifacialmocap";
61
62
  "vts-ios": "vts-ios";
62
63
  vmc: "vmc";
63
64
  mocopi: "mocopi";
64
- mediapipe: "mediapipe";
65
65
  }>;
66
66
  name: z.ZodString;
67
67
  enabled: z.ZodBoolean;
@@ -123,12 +123,12 @@ export declare const TrackingSettingsSchema: z.ZodObject<{
123
123
  sources: z.ZodArray<z.ZodObject<{
124
124
  id: z.ZodString;
125
125
  kind: z.ZodEnum<{
126
+ mediapipe: "mediapipe";
126
127
  "persona-ios": "persona-ios";
127
128
  ifacialmocap: "ifacialmocap";
128
129
  "vts-ios": "vts-ios";
129
130
  vmc: "vmc";
130
131
  mocopi: "mocopi";
131
- mediapipe: "mediapipe";
132
132
  }>;
133
133
  name: z.ZodString;
134
134
  enabled: z.ZodBoolean;
@@ -209,12 +209,12 @@ export declare const SettingsSchema: z.ZodObject<{
209
209
  sources: z.ZodArray<z.ZodObject<{
210
210
  id: z.ZodString;
211
211
  kind: z.ZodEnum<{
212
+ mediapipe: "mediapipe";
212
213
  "persona-ios": "persona-ios";
213
214
  ifacialmocap: "ifacialmocap";
214
215
  "vts-ios": "vts-ios";
215
216
  vmc: "vmc";
216
217
  mocopi: "mocopi";
217
- mediapipe: "mediapipe";
218
218
  }>;
219
219
  name: z.ZodString;
220
220
  enabled: z.ZodBoolean;
@@ -1,16 +1,16 @@
1
1
  import * as z from 'zod';
2
2
  import { CONTROLLER_DEAD_ZONE_MAX } from "../../values/controller.js";
3
3
  import { LIP_SYNC_GAIN_MAX, LIP_SYNC_MAX_SAMPLES, LIP_SYNC_MFCC_COEFFICIENTS, LIP_SYNC_MIN_SAMPLES, LIP_SYNC_NOISE_GATE_MIN, LIP_SYNC_PHONEMES, LIP_SYNC_SMOOTHING_MAX, } from "../../values/lipsync.js";
4
- import { LOCALES } from "../../values/locale.js";
4
+ import { LANGUAGE_SETTINGS, THEME_SETTINGS } from "../../values/locale.js";
5
5
  import { EFFECTS_QUALITY_LEVELS, MEDIAPIPE_DELEGATES, POSE_SOURCE_IDS, TRACKING_SOURCE_IDS, TRACKING_SOURCE_KINDS, } from "../types.js";
6
6
  /** Shared field definitions; parsing validates values without adding defaults or healing them. */
7
7
  export const PortSchema = z.number().int().min(1).max(65535).describe('Network port, from 1 through 65535.');
8
8
  export const EffectsQualitySchema = z.enum(EFFECTS_QUALITY_LEVELS).describe('Scene and layer effects quality tier.');
9
9
  export const LanguageSettingSchema = z
10
- .enum(['system', ...LOCALES])
10
+ .enum(LANGUAGE_SETTINGS)
11
11
  .describe('Interface language, or system to follow the operating system.');
12
12
  export const ThemeSettingSchema = z
13
- .enum(['system', 'light', 'dark'])
13
+ .enum(THEME_SETTINGS)
14
14
  .describe('Interface appearance, or system to follow the operating system.');
15
15
  /** Microphone configuration shared by desktop persistence and the plugin API. */
16
16
  export const LipSyncConfigSchema = z.object({
@@ -1,5 +1,5 @@
1
1
  import type * as z from 'zod';
2
- import type { EFFECT_BLEND_MODES, EFFECT_SCOPES } from '../values/effect-schema.ts';
2
+ import type { BLOOM_MODES, BLUR_MODES, BloomColorSlot, COLOR_SHIFT_BANDS, COLOR_WHEELS_MODES, EFFECT_BLEND_MODES, EFFECT_SCOPES, EFFECTS_QUALITY_LEVELS, FLARE_MODES, FLARE_RAYS_MODES, GRADIENT_TYPES, LEVEL_CHANNELS, RIM_MODES, SelectColorsSlot } from '../values/effect-schema.ts';
3
3
  import type { ItemTransition } from '../values/item-transition.ts';
4
4
  import type { SCENE_TRANSITION_TYPES } from '../values/scene-transition.ts';
5
5
  import type { SettingsPatchSchema, SettingsSchema } from './schemas/settings.ts';
@@ -9,9 +9,11 @@ import { type HandInputName } from '../values/hands.ts';
9
9
  import { type LipSyncMode, type VoiceInputName } from '../values/lipsync.ts';
10
10
  import { type MouseInputName } from '../values/mouse.ts';
11
11
  import { type TimeInputName } from '../values/time.ts';
12
- export type ModelFormat = 'live2d' | 'vrm';
12
+ export declare const MODEL_FORMATS: readonly ["live2d", "vrm"];
13
+ export type ModelFormat = (typeof MODEL_FORMATS)[number];
14
+ export declare const CONTENT_ORIGINS: readonly ["bundled", "user"];
13
15
  /** Where an item came from: shipped with the app, or added by the user. */
14
- export type ContentOrigin = 'bundled' | 'user';
16
+ export type ContentOrigin = (typeof CONTENT_ORIGINS)[number];
15
17
  /**
16
18
  * How a registered file is labelled. Wider than an object's content kinds: `.hdr` is only
17
19
  * ever an environment map, and a `.vmd` splits by content — `cameraMotion` for one that
@@ -55,6 +57,8 @@ export interface ModelRef extends ContentRef {
55
57
  * without one. Only `model.list` fills it: absent on scene item refs, `model.register`'s answer, and older hosts.
56
58
  */
57
59
  vtubeFile?: string | null;
60
+ /** False once the entry file is gone from disk, like {@link AssetRef.exists}; filled like {@link ModelRef.vtubeFile}. */
61
+ exists?: boolean;
58
62
  }
59
63
  /** A registered object-source file. `exists` is false once the file is gone from disk. */
60
64
  export interface AssetRef extends ContentRef {
@@ -215,7 +219,8 @@ export interface SceneModelItem {
215
219
  }
216
220
  export declare const OBJECT_SPACES: readonly ["2d", "3d"];
217
221
  export type ObjectSpace = (typeof OBJECT_SPACES)[number];
218
- export type CaptureKind = 'display' | 'window';
222
+ export declare const CAPTURE_KINDS: readonly ["display", "window"];
223
+ export type CaptureKind = (typeof CAPTURE_KINDS)[number];
219
224
  export declare const TEXT_ALIGNS: readonly ["left", "center", "right", "justify"];
220
225
  export type TextAlign = (typeof TEXT_ALIGNS)[number];
221
226
  /** `baseline` is the first line's baseline — Blender's Top Base-Line. */
@@ -487,7 +492,8 @@ export interface SceneObjectItem {
487
492
  }
488
493
  /** Anything the stage renders. Array order in {@link Scene.items} is z-order within each space. */
489
494
  export type SceneItem = SceneModelItem | SceneObjectItem;
490
- export type BackgroundMode = 'transparent' | 'color' | 'image';
495
+ export declare const BACKGROUND_MODES: readonly ["transparent", "color", "image"];
496
+ export type BackgroundMode = (typeof BACKGROUND_MODES)[number];
491
497
  /** `imageAssetId` names a registered asset; an id this app cannot resolve renders transparent. */
492
498
  export interface SceneBackground {
493
499
  mode: BackgroundMode;
@@ -607,6 +613,8 @@ export interface SceneCameraHandheld {
607
613
  /** 0–2; 1 sways at the authored pace. */
608
614
  speed: number;
609
615
  }
616
+ export declare const CAMERA_PROJECTIONS: readonly ["perspective", "orthographic"];
617
+ export type CameraProjection = (typeof CAMERA_PROJECTIONS)[number];
610
618
  /** Scene-level VRM camera. `orbit: null` = never framed — the first VRM load frames it from model height. */
611
619
  export interface SceneCamera {
612
620
  orbit: OrbitTransform | null;
@@ -615,7 +623,7 @@ export interface SceneCamera {
615
623
  /** Rotation about camera-local +Z in radians; absent on older hosts, default 0. */
616
624
  roll?: number;
617
625
  /** Absent on older hosts; defaults to perspective. */
618
- projection?: 'perspective' | 'orthographic';
626
+ projection?: CameraProjection;
619
627
  /**
620
628
  * A `cameraMotion` asset driving the camera, or null for the user's own orbit. While one
621
629
  * is set it overrides the framing every frame without writing it back.
@@ -678,7 +686,7 @@ export interface SceneLight {
678
686
  type: SceneLightType;
679
687
  /** Mutes illumination and shadows. Defaults to true; omitted by hosts without light toggles. */
680
688
  enabled?: boolean;
681
- /** Camera-relative placement and angles; defaults to false. Gate editing on `camera-follow-lights`; ambient ignores it. */
689
+ /** Camera-relative placement and angles; defaults to false. Gate editing on `light-camera-follow`; ambient ignores it. */
682
690
  followCamera?: boolean;
683
691
  /** Independent camera components; omitted means all true. */
684
692
  followCameraOptions?: SceneLightCameraFollowOptions;
@@ -710,7 +718,7 @@ export interface SceneLight {
710
718
  shadowQuality: ShadowQuality;
711
719
  /** PCF disk radius in shadow-map texels; retained while PCSS is selected. */
712
720
  shadowRadius: number;
713
- /** Per-light filter; defaults to PCF. Gate editing on the `shadow-filters` app capability. */
721
+ /** Per-light filter; defaults to PCF. Gate editing on the `light-shadow-filter` app capability. */
714
722
  shadowFilter?: ShadowFilter;
715
723
  /** PCSS source diameter: degrees for directional lights, metres for point/spot; 0–10, default 0.1. */
716
724
  shadowSourceSize?: number;
@@ -735,11 +743,15 @@ export interface SceneVolumetricLighting {
735
743
  speed: number;
736
744
  }
737
745
  /** Display transform applied after the scene renders. `none` keeps colors exactly as authored. */
738
- export type SceneToneMapping = 'none' | 'neutral' | 'aces' | 'agx';
746
+ export declare const SCENE_TONE_MAPPINGS: readonly ["none", "neutral", "aces", "agx"];
747
+ export type SceneToneMapping = (typeof SCENE_TONE_MAPPINGS)[number];
748
+ export type BloomMode = (typeof BLOOM_MODES)[number];
749
+ /** An effect's color slots, `color1` up, each with its `Enabled` switch. */
750
+ type ColorSlots<Slot extends number> = Record<`color${Slot}`, string> & Record<`color${Slot}Enabled`, boolean>;
739
751
  /** Highlight glow in normal, streak, or star mode; color selection applies only to layer effects. */
740
- export interface SceneBloom {
752
+ export interface SceneBloom extends ColorSlots<BloomColorSlot> {
741
753
  enabled: boolean;
742
- mode: 'normal' | 'streak' | 'star';
754
+ mode: BloomMode;
743
755
  /** The glow's brightness multiplier, as Warudo's; 0 adds no glow. */
744
756
  intensity: number;
745
757
  /** Gamma-space brightness a channel must pass; squared into linear light, as Warudo's. */
@@ -756,16 +768,6 @@ export interface SceneBloom {
756
768
  invertColors: boolean;
757
769
  /** Shared saturation/brightness tolerance; hue tolerance is fixed at 0.03. */
758
770
  colorTolerance: number;
759
- color1: string;
760
- color2: string;
761
- color3: string;
762
- color4: string;
763
- color5: string;
764
- color1Enabled: boolean;
765
- color2Enabled: boolean;
766
- color3Enabled: boolean;
767
- color4Enabled: boolean;
768
- color5Enabled: boolean;
769
771
  }
770
772
  /**
771
773
  * Cinematic soft-focus veil (Shoost's diffusion, a Kino bloom variant): the
@@ -799,34 +801,19 @@ export interface SceneColorGrade {
799
801
  /** White balance along green↔magenta, −100..100 — the axis `temperature` leaves alone. */
800
802
  tint: number;
801
803
  }
804
+ /** A Levels color channel, suffixing its copy of every {@link LevelParam}. */
805
+ export type LevelChannel = (typeof LEVEL_CHANNELS)[number];
806
+ /** One channel's levels; the master set carries no suffix. */
807
+ export type LevelParam = 'inputBlack' | 'inputWhite' | 'inputGamma' | 'outputBlack' | 'outputWhite';
802
808
  /** Master and per-channel input/output levels; RGB channels run before master levels. */
803
- export interface EffectLevels {
809
+ export interface EffectLevels extends Record<`${LevelParam}${'' | LevelChannel}`, number> {
804
810
  enabled: boolean;
805
- inputBlack: number;
806
- inputWhite: number;
807
- inputGamma: number;
808
- outputBlack: number;
809
- outputWhite: number;
810
- inputBlackR: number;
811
- inputWhiteR: number;
812
- inputGammaR: number;
813
- outputBlackR: number;
814
- outputWhiteR: number;
815
- inputBlackG: number;
816
- inputWhiteG: number;
817
- inputGammaG: number;
818
- outputBlackG: number;
819
- outputWhiteG: number;
820
- inputBlackB: number;
821
- inputWhiteB: number;
822
- inputGammaB: number;
823
- outputBlackB: number;
824
- outputWhiteB: number;
825
811
  }
812
+ export type ColorWheelsMode = (typeof COLOR_WHEELS_MODES)[number];
826
813
  /** Color wheels in lift/gamma/gain or shadows/midtones/highlights mode. */
827
814
  export interface EffectColorWheels {
828
815
  enabled: boolean;
829
- mode: 'liftGammaGain' | 'shadowsMidtonesHighlights';
816
+ mode: ColorWheelsMode;
830
817
  lift: number;
831
818
  liftColor: string;
832
819
  gamma: number;
@@ -842,36 +829,16 @@ export interface EffectColorWheels {
842
829
  shadowLimit: number;
843
830
  highlightLimit: number;
844
831
  }
845
- /** Six hue bands; hue offsets are degrees, other offsets are -1..1. */
846
- export interface EffectColorShift {
832
+ /** A Color Shift hue band, suffixing its copy of every {@link ColorShiftParam}. */
833
+ export type ColorShiftBand = (typeof COLOR_SHIFT_BANDS)[number];
834
+ /** One hue band's offsets. */
835
+ export type ColorShiftParam = 'hue' | 'saturation' | 'luminance' | 'luminanceSaturation';
836
+ /** Per-band offsets; hue offsets are degrees, other offsets are -1..1. */
837
+ export interface EffectColorShift extends Record<`${ColorShiftParam}${ColorShiftBand}`, number> {
847
838
  enabled: boolean;
848
- hueRed: number;
849
- saturationRed: number;
850
- luminanceRed: number;
851
- luminanceSaturationRed: number;
852
- hueYellow: number;
853
- saturationYellow: number;
854
- luminanceYellow: number;
855
- luminanceSaturationYellow: number;
856
- hueGreen: number;
857
- saturationGreen: number;
858
- luminanceGreen: number;
859
- luminanceSaturationGreen: number;
860
- hueCyan: number;
861
- saturationCyan: number;
862
- luminanceCyan: number;
863
- luminanceSaturationCyan: number;
864
- hueBlue: number;
865
- saturationBlue: number;
866
- luminanceBlue: number;
867
- luminanceSaturationBlue: number;
868
- hueMagenta: number;
869
- saturationMagenta: number;
870
- luminanceMagenta: number;
871
- luminanceSaturationMagenta: number;
872
839
  }
873
840
  /** Preserve selected colors while adjusting saturation outside their HSV ranges. */
874
- export interface EffectSelectColors {
841
+ export interface EffectSelectColors extends ColorSlots<SelectColorsSlot> {
875
842
  enabled: boolean;
876
843
  invert: boolean;
877
844
  /** Hue distance in turns around the color wheel. */
@@ -881,32 +848,13 @@ export interface EffectSelectColors {
881
848
  /** Saturation offset outside the selection; -1 makes it monochrome. */
882
849
  saturation: number;
883
850
  blend: number;
884
- color1: string;
885
- color1Enabled: boolean;
886
- color2: string;
887
- color2Enabled: boolean;
888
- color3: string;
889
- color3Enabled: boolean;
890
- color4: string;
891
- color4Enabled: boolean;
892
- color5: string;
893
- color5Enabled: boolean;
894
- color6: string;
895
- color6Enabled: boolean;
896
- color7: string;
897
- color7Enabled: boolean;
898
- color8: string;
899
- color8Enabled: boolean;
900
- color9: string;
901
- color9Enabled: boolean;
902
- color10: string;
903
- color10Enabled: boolean;
904
851
  }
852
+ export type BlurMode = (typeof BLUR_MODES)[number];
905
853
  /** Gaussian or disk-shaped bokeh blur in output pixels. */
906
854
  export interface EffectBlur {
907
855
  enabled: boolean;
908
856
  radius: number;
909
- mode: 'gaussian' | 'bokeh';
857
+ mode: BlurMode;
910
858
  highQuality: boolean;
911
859
  }
912
860
  /**
@@ -1013,10 +961,11 @@ export interface SceneDroplets {
1013
961
  }
1014
962
  /** Shoost's blend modes, as Gradient offers them. */
1015
963
  export type EffectBlendMode = (typeof EFFECT_BLEND_MODES)[number];
964
+ export type GradientType = (typeof GRADIENT_TYPES)[number];
1016
965
  /** Solid, linear, or radial color overlay in scene or source coordinates. */
1017
966
  export interface EffectGradient {
1018
967
  enabled: boolean;
1019
- type: 'solid' | 'linear' | 'circle' | 'ellipse';
968
+ type: GradientType;
1020
969
  blendMode: EffectBlendMode;
1021
970
  /** Foreground color (hex). */
1022
971
  color: string;
@@ -1036,10 +985,12 @@ export interface EffectGradient {
1036
985
  scaleY: number;
1037
986
  opacity: number;
1038
987
  }
988
+ export type FlareMode = (typeof FLARE_MODES)[number];
989
+ export type FlareRaysMode = (typeof FLARE_RAYS_MODES)[number];
1039
990
  /** Directional screen-space light with an independent monitor glow. */
1040
991
  export interface SceneFlare {
1041
992
  enabled: boolean;
1042
- mode: 'add' | 'screen' | 'colorDodge';
993
+ mode: FlareMode;
1043
994
  /** Light color (hex). */
1044
995
  color: string;
1045
996
  intensity: number;
@@ -1048,17 +999,18 @@ export interface SceneFlare {
1048
999
  angle: number;
1049
1000
  glowOpacity: number;
1050
1001
  rays: boolean;
1051
- raysMode: 'sun' | 'shine' | 'god';
1002
+ raysMode: FlareRaysMode;
1052
1003
  /** Particle-ray color (hex). */
1053
1004
  raysColor: string;
1054
1005
  raysScale: number;
1055
1006
  raysIntensity: number;
1056
1007
  raysOpacity: number;
1057
1008
  }
1009
+ export type RimMode = (typeof RIM_MODES)[number];
1058
1010
  /** Directional silhouette light, added like VTube Studio's backlight; optionally sharpened or two-sided. */
1059
1011
  export interface SceneRim {
1060
1012
  enabled: boolean;
1061
- mode: 'single' | 'double' | 'sharpenSingle' | 'sharpenDouble';
1013
+ mode: RimMode;
1062
1014
  /** Rim tint (hex). */
1063
1015
  color: string;
1064
1016
  /** Normalized rim width, 0..1. */
@@ -1072,7 +1024,7 @@ export interface SceneRim {
1072
1024
  /** Solid silhouette border; quality sets how closely it follows fine detail. */
1073
1025
  export interface SceneOutline {
1074
1026
  enabled: boolean;
1075
- quality: 'low' | 'medium' | 'high';
1027
+ quality: EffectsQuality;
1076
1028
  /** Outline color (hex). */
1077
1029
  color: string;
1078
1030
  /** Normalized border thickness, 0..1. */
@@ -1312,29 +1264,21 @@ export interface ScenePatch {
1312
1264
  /**
1313
1265
  * App-level features a client gates on (never version-sniff): `hello` and
1314
1266
  * `app.info` report them — the per-app mirror of {@link InstanceRuntime.capabilities}.
1267
+ * Each name leads with what it extends (`light-spot`, `object-text`), as action kinds do.
1315
1268
  */
1316
- export declare const APP_CAPABILITIES: readonly ["storage", "speech", "automations", "controllers", "model-editing", "asset-inspection", "layer-effects", "scene-transitions", "area-lights", "spot-lights", "camera-follow-lights", "shadow-filters", "environment-map-model", "spawn", "tracking-lost", "motion-stop", "stage-capture", "model-movement", "object-pin-depth", "text-objects", "camera-follow", "camera-aim", "camera-focus", "camera-handheld", "video-sound", "object-chroma-key"];
1269
+ export declare const APP_CAPABILITIES: readonly ["storage", "speech", "automations", "controllers", "model-editing", "asset-inspection", "layer-effects", "scene-transitions", "light-area", "light-spot", "light-camera-follow", "light-shadow-filter", "environment-map-model", "stage-spawn", "idle-tracking-lost", "motion-stop", "stage-capture", "model-movement", "object-pin-depth", "object-text", "camera-follow", "camera-aim", "camera-focus", "camera-handheld", "object-video-sound", "object-chroma-key", "model-movement-pivot", "layer-effects-2d"];
1317
1270
  export type AppCapability = (typeof APP_CAPABILITIES)[number];
1318
1271
  export declare function isAppCapability(v: unknown): v is AppCapability;
1319
- /** What a loaded model instance can do; absent capabilities answer `unsupported-for-format`. */
1320
- export type InstanceCapability = 'motions' | 'expressions' | 'placement-2d' | 'placement-3d' | 'mtoon' | 'idle-clips'
1321
- /** `instance.setIdle` with `idleMotion`: one of the model's motions loops as its idle. Live2D only. */
1322
- | 'idle-motions' | 'pose' | 'live2d-params'
1323
- /** `instance.setBreath`; the idle breathing loop is Cubism's, so VRM lacks it. */
1324
- | 'breath'
1325
- /** `expression.setWeight`; Cubism expressions carry no user-settable weight, so Live2D lacks it. */
1326
- | 'expression-weights'
1327
1272
  /**
1328
- * `speech.play` lip-sync. Loaded Live2D models only; 0.53 and earlier hosts also omit it under
1329
- * the Pixi engine, so gate on the runtime, not the format.
1273
+ * Old app capability names, each mapped to its category-first replacement. Hosts still list them for
1274
+ * clients from before the rename; the SDK client folds them into the new names on receipt.
1330
1275
  */
1331
- | 'speech'
1332
- /**
1333
- * Draws through the 3D post chain, so the scene's look rows (tone mapping, exposure, LUT)
1334
- * reach it. Every model; 0.53 and earlier hosts omit it on Pixi-engine Live2D, so read it off
1335
- * the runtime rather than the format.
1336
- */
1337
- | 'post-fx';
1276
+ export declare const LEGACY_APP_CAPABILITIES: ReadonlyMap<string, AppCapability>;
1277
+ /** The current name of an app capability; names that were never renamed, known or not, pass through. */
1278
+ export declare function canonicalAppCapability(name: string): string;
1279
+ /** What a loaded model instance can do; absent capabilities answer `unsupported-for-format`. */
1280
+ export declare const INSTANCE_CAPABILITIES: readonly ["motions", "expressions", "placement-2d", "placement-3d", "mtoon", "idle-clips", "idle-motions", "pose", "live2d-params", "breath", "expression-weights", "speech", "post-fx"];
1281
+ export type InstanceCapability = (typeof INSTANCE_CAPABILITIES)[number];
1338
1282
  export interface InstanceRuntime {
1339
1283
  instanceId: string;
1340
1284
  kind: 'model' | 'object';
@@ -1378,14 +1322,20 @@ export interface AnchorOption {
1378
1322
  }
1379
1323
  export type { ModelInfo } from '../values/model-info.ts';
1380
1324
  export interface Hotkey {
1325
+ /** VTS `HotkeyID`: 32 lowercase hex chars when Persona mints it. */
1381
1326
  id: string;
1382
1327
  name: string;
1383
1328
  /** The VTS `Action` string verbatim; `action` is null when Persona cannot run it. */
1384
1329
  vtsAction: string;
1330
+ /** Derived from `vtsAction`; `hotkey.set` ignores the value a client sends. */
1385
1331
  action: 'expression-toggle' | 'motion-play' | 'expression-clear' | 'model-load' | null;
1332
+ /** A `hotkeyTargets` file, or the model's for model-load (see `modelMatchesFile`); empty for expression-clear. */
1386
1333
  file: string;
1334
+ /** Keyboard accelerator or `Controller*` combo; null when the stored triggers are unsupported. */
1387
1335
  accelerator: string | null;
1336
+ /** VTS `IsGlobal`: the user's intent, independent of whether registration succeeded. */
1388
1337
  global: boolean;
1338
+ /** VTS `IsActive`; an inactive hotkey never fires. */
1389
1339
  active: boolean;
1390
1340
  /** Expression: on only while the combo is held down (VTS `DeactivateAfterKeyUp`). Default false. */
1391
1341
  hold?: boolean;
@@ -1397,6 +1347,7 @@ export interface Hotkey {
1397
1347
  stopsOnLastFrame?: boolean;
1398
1348
  }
1399
1349
  export interface HotkeyConfig {
1350
+ /** The model's master switch (VTS `HotkeySettings.UseKeyboardHotkeys`). */
1400
1351
  keyboardEnabled: boolean;
1401
1352
  hotkeys: Hotkey[];
1402
1353
  }
@@ -1469,6 +1420,8 @@ export declare const TRACKING_CHANNEL_FIELDS: {
1469
1420
  readonly hands: "handSourceId";
1470
1421
  };
1471
1422
  export declare const TRACKING_CHANNELS: readonly TrackingChannel[];
1423
+ /** A model item's source binding for each channel, the fields {@link TRACKING_CHANNEL_FIELDS} names. */
1424
+ export type ChannelBindings = Pick<SceneModelItem, (typeof TRACKING_CHANNEL_FIELDS)[TrackingChannel]>;
1472
1425
  export declare const HAND_TRACKING_MODES: readonly ["arms", "fingers"];
1473
1426
  /** How the face drivers react to a dropout; see `SceneModelInstance.trackingLostBehavior`. */
1474
1427
  export declare const TRACKING_LOST_BEHAVIORS: readonly ["hold", "idle"];
@@ -1534,7 +1487,7 @@ export declare function sourceChannelEnabled(source: TrackingSourceConfig, chann
1534
1487
  * share one socket per port (frames demux by phone); every other pairing EADDRINUSEs a listener.
1535
1488
  */
1536
1489
  export declare function trackingPortTaken(sources: readonly TrackingSourceConfig[], kind: TrackingSourceKind, port: number, excludeId?: string): boolean;
1537
- export declare const EFFECTS_QUALITY_LEVELS: readonly ["low", "medium", "high"];
1490
+ export { EFFECTS_QUALITY_LEVELS } from '../values/effect-schema.ts';
1538
1491
  export type EffectsQuality = (typeof EFFECTS_QUALITY_LEVELS)[number];
1539
1492
  /**
1540
1493
  * Accepted values for `performance.fpsLimit`; 0 = unlimited. Anything else is snapped