@laplace.live/persona-sdk 1.4.0 → 1.5.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.
@@ -0,0 +1,14 @@
1
+ import type { AssetRef, SceneTransition } from '../wire/types.ts';
2
+ export declare const SCENE_TRANSITION_TYPES: readonly ["cut", "fade", "wipe", "circle", "image", "video"];
3
+ export declare const SCENE_TRANSITION_DURATION_MIN_MS = 100;
4
+ export declare const SCENE_TRANSITION_DURATION_MAX_MS = 10000;
5
+ export declare const SCENE_TRANSITION_SWITCH_POINT_MIN = 0.05;
6
+ export declare const SCENE_TRANSITION_SWITCH_POINT_MAX = 0.95;
7
+ /** The destination scene's entrance effect; existing scenes keep an immediate cut. */
8
+ export declare function defaultSceneTransition(): SceneTransition;
9
+ /** The media kind a transition type plays, or null for the built-in effects. */
10
+ export declare function sceneTransitionMedia(type: SceneTransition['type']): 'image' | 'video' | null;
11
+ /** Whether `asset` can back the transition: an available image or video, matching the type when it plays media. */
12
+ export declare function sceneTransitionAssetUsable(transition: SceneTransition, asset: Pick<AssetRef, 'kind' | 'exists'> | null | undefined): boolean;
13
+ /** Heal saved transition settings independently, retaining media while another effect is selected. */
14
+ export declare function healSceneTransition(raw: unknown): SceneTransition;
@@ -0,0 +1,36 @@
1
+ import { finiteOr, isOneOf, isRecord, nonEmptyString } from "./guards.js";
2
+ import { clamp, hexColorOr } from "./limits.js";
3
+ export const SCENE_TRANSITION_TYPES = ['cut', 'fade', 'wipe', 'circle', 'image', 'video'];
4
+ export const SCENE_TRANSITION_DURATION_MIN_MS = 100;
5
+ export const SCENE_TRANSITION_DURATION_MAX_MS = 10_000;
6
+ export const SCENE_TRANSITION_SWITCH_POINT_MIN = 0.05;
7
+ export const SCENE_TRANSITION_SWITCH_POINT_MAX = 0.95;
8
+ /** The destination scene's entrance effect; existing scenes keep an immediate cut. */
9
+ export function defaultSceneTransition() {
10
+ return { type: 'cut', durationMs: 1000, color: '#000000', assetId: null, switchPoint: 0.5, autoFade: false };
11
+ }
12
+ /** The media kind a transition type plays, or null for the built-in effects. */
13
+ export function sceneTransitionMedia(type) {
14
+ return type === 'image' || type === 'video' ? type : null;
15
+ }
16
+ /** Whether `asset` can back the transition: an available image or video, matching the type when it plays media. */
17
+ export function sceneTransitionAssetUsable(transition, asset) {
18
+ if (!asset?.exists || (asset.kind !== 'image' && asset.kind !== 'video'))
19
+ return false;
20
+ const media = sceneTransitionMedia(transition.type);
21
+ return media === null || asset.kind === media;
22
+ }
23
+ /** Heal saved transition settings independently, retaining media while another effect is selected. */
24
+ export function healSceneTransition(raw) {
25
+ const d = defaultSceneTransition();
26
+ if (!isRecord(raw))
27
+ return d;
28
+ return {
29
+ type: isOneOf(raw.type, SCENE_TRANSITION_TYPES) ? raw.type : d.type,
30
+ durationMs: clamp(finiteOr(raw.durationMs, d.durationMs), SCENE_TRANSITION_DURATION_MIN_MS, SCENE_TRANSITION_DURATION_MAX_MS),
31
+ color: hexColorOr(raw.color, d.color),
32
+ assetId: nonEmptyString(raw.assetId),
33
+ switchPoint: clamp(finiteOr(raw.switchPoint, d.switchPoint), SCENE_TRANSITION_SWITCH_POINT_MIN, SCENE_TRANSITION_SWITCH_POINT_MAX),
34
+ autoFade: typeof raw.autoFade === 'boolean' ? raw.autoFade : d.autoFade,
35
+ };
36
+ }
@@ -1,10 +1,11 @@
1
+ import { isOneOf } from "../values/guards.js";
1
2
  /** Every error the server can return, as string discriminants (never numeric bands). */
2
3
  export const API_ERROR_CODES = [
3
4
  'parse-error',
4
5
  'invalid-request',
5
6
  'unknown-method',
6
7
  'invalid-params',
7
- /** A referenced id (scene, instance, model, asset, hotkey, shortcut, expression) resolves to nothing. */
8
+ /** A referenced id (scene, instance, model, asset, hotkey, automation, expression) resolves to nothing. */
8
9
  'not-found',
9
10
  /** The instance's model format cannot perform this method (e.g. MToon on Live2D). */
10
11
  'unsupported-for-format',
@@ -19,7 +20,7 @@ export const API_ERROR_CODES = [
19
20
  'internal',
20
21
  ];
21
22
  export function isApiErrorCode(v) {
22
- return typeof v === 'string' && API_ERROR_CODES.includes(v);
23
+ return isOneOf(v, API_ERROR_CODES);
23
24
  }
24
25
  /** Thrown by {@link PersonaClient.call} when the server answers with an error envelope. */
25
26
  export class PersonaApiError extends Error {
@@ -1,4 +1,4 @@
1
- import type { ExpressionPersistence, HotkeyState, ModelFormat, PoseStatus, SceneState, Settings, ShortcutInfo, TrackingStatus } from './types.ts';
1
+ import type { AutomationInfo, ExpressionPersistence, HotkeyState, ModelFormat, PoseStatus, SceneState, Settings, TrackingStatus } from './types.ts';
2
2
  /** Every push event a session can subscribe to, with its payload. */
3
3
  export interface EventMap {
4
4
  /** Any scene mutation: create/delete/rename/activate/shortcut and persisted scene edits. */
@@ -10,9 +10,9 @@ export interface EventMap {
10
10
  modelId: string | null;
11
11
  config: HotkeyState;
12
12
  };
13
- /** The app-shortcut list, its names, or its OS registrations changed. */
14
- 'shortcut.state': {
15
- shortcuts: ShortcutInfo[];
13
+ /** The automation list, its names, or its OS registrations changed. */
14
+ 'automation.state': {
15
+ automations: AutomationInfo[];
16
16
  };
17
17
  /** Network channel aggregates; `sources` includes webcam status and is optional for older servers. */
18
18
  'tracking.status': {
@@ -1,10 +1,11 @@
1
+ import { isOneOf } from "../values/guards.js";
1
2
  // Built from a `Record<EventName, …>` so a new EventMap key that is missing
2
3
  // here fails the build instead of silently failing `isEventName`.
3
4
  export const EVENT_NAMES = Object.keys({
4
5
  'scene.changed': true,
5
6
  'settings.changed': true,
6
7
  'hotkey.state': true,
7
- 'shortcut.state': true,
8
+ 'automation.state': true,
8
9
  'tracking.status': true,
9
10
  'instance.loaded': true,
10
11
  'expression.changed': true,
@@ -18,5 +19,5 @@ export const EVENT_NAMES = Object.keys({
18
19
  'expression.persistence': true,
19
20
  });
20
21
  export function isEventName(v) {
21
- return typeof v === 'string' && EVENT_NAMES.includes(v);
22
+ return isOneOf(v, EVENT_NAMES);
22
23
  }
@@ -3,7 +3,7 @@ import type { ControllerMovementConfig, ControllerState } from '../values/contro
3
3
  import type { LipSyncCalibrationCommand, LipSyncConfig, LipSyncMode, LipSyncState } from '../values/lipsync.ts';
4
4
  import type { SceneInspection } from '../values/stage-info.ts';
5
5
  import type { EventName } from './events.ts';
6
- import type { AnchorOption, AppCapability, AssetKind, AssetRef, Attach, AttachHeadAngle, BindingInput, Expression, ExpressionPersistence, HandTrackingMode, HotkeyConfig, HotkeyState, InjectEntry, InjectTarget, InstanceRuntime, JsonValue, LayerEffectKey, LayerEffects, LayerEffectsPatch, MediaPipeConfig, ModelInfo, ModelRef, MotionGroup, MToonTuning, ObjectContent, ObjectLightOverride, ObjectSpace, Place2D, Place3D, PlayingMotion, PoseSourceId, PoseStatus, Scene, SceneItem, ScenePatch, SceneState, ScreenPlacement, Settings, SettingsPatch, ShortcutInfo, TrackingSourceConfig, TrackingSourceId, TrackingSourceKind, TrackingStatus, VrmPlacement } from './types.ts';
6
+ import type { AnchorOption, AppCapability, AssetKind, AssetRef, Attach, AttachHeadAngle, AutomationInfo, BindingInput, Expression, ExpressionPersistence, HandTrackingMode, HotkeyConfig, HotkeyState, InjectEntry, InjectTarget, InstanceRuntime, JsonValue, LayerEffectKey, LayerEffects, LayerEffectsPatch, MediaPipeConfig, ModelInfo, ModelRef, MotionGroup, MToonTuning, ObjectContent, ObjectLightOverride, ObjectSpace, Place2D, Place3D, PlayingMotion, PoseSourceId, PoseStatus, Scene, SceneItem, ScenePatch, SceneState, ScreenPlacement, Settings, SettingsPatch, TrackingSourceConfig, TrackingSourceId, TrackingSourceKind, TrackingStatus, VrmPlacement } from './types.ts';
7
7
  /** Marker for methods that take no parameters; the client lets you omit the argument. */
8
8
  export type EmptyRequest = Record<never, never>;
9
9
  /** Marker for methods whose success response carries no data. */
@@ -295,14 +295,14 @@ export interface HotkeyTriggerRequest {
295
295
  hotkeyId: string;
296
296
  }
297
297
  export type HotkeyTriggerResponse = EmptyResponse;
298
- export type ShortcutListRequest = EmptyRequest;
299
- export interface ShortcutListResponse {
300
- shortcuts: ShortcutInfo[];
298
+ export type AutomationListRequest = EmptyRequest;
299
+ export interface AutomationListResponse {
300
+ automations: AutomationInfo[];
301
301
  }
302
- export interface ShortcutTriggerRequest {
303
- shortcutId: string;
302
+ export interface AutomationRunRequest {
303
+ automationId: string;
304
304
  }
305
- export type ShortcutTriggerResponse = EmptyResponse;
305
+ export type AutomationRunResponse = EmptyResponse;
306
306
  export type ModelListRequest = EmptyRequest;
307
307
  export interface ModelListResponse {
308
308
  models: ModelRef[];
@@ -842,13 +842,13 @@ export interface MethodMap {
842
842
  request: HotkeyTriggerRequest;
843
843
  response: HotkeyTriggerResponse;
844
844
  };
845
- 'shortcut.list': {
846
- request: ShortcutListRequest;
847
- response: ShortcutListResponse;
845
+ 'automation.list': {
846
+ request: AutomationListRequest;
847
+ response: AutomationListResponse;
848
848
  };
849
- 'shortcut.trigger': {
850
- request: ShortcutTriggerRequest;
851
- response: ShortcutTriggerResponse;
849
+ 'automation.run': {
850
+ request: AutomationRunRequest;
851
+ response: AutomationRunResponse;
852
852
  };
853
853
  'model.list': {
854
854
  request: ModelListRequest;
@@ -1,10 +1,12 @@
1
1
  import type { InjectTarget } from './types.ts';
2
2
  /** Bumped on breaking wire changes; the server reports it in `hello` and clients warn on mismatch. */
3
- export declare const PROTOCOL_VERSION = 3;
3
+ export declare const PROTOCOL_VERSION = 4;
4
4
  /** Default port the Persona API server listens on (user-configurable in the app). */
5
5
  export declare const DEFAULT_API_PORT = 25034;
6
6
  /** Default host clients dial: the server binds loopback unless LAN is opted in. */
7
7
  export declare const DEFAULT_API_HOST = "127.0.0.1";
8
+ /** Scene activation waits for asset preparation before committing the new scene. */
9
+ export declare const SCENE_ACTIVATION_TIMEOUT_MS = 120000;
8
10
  /** Server close code: the session's API key was revoked. Terminal — the client must not redial. */
9
11
  export declare const CLOSE_KEY_REVOKED = 4001;
10
12
  /** Server close code: the user disconnected this session from Persona's settings. Terminal — the client must not redial. */
@@ -1,9 +1,11 @@
1
1
  /** Bumped on breaking wire changes; the server reports it in `hello` and clients warn on mismatch. */
2
- export const PROTOCOL_VERSION = 3;
2
+ export const PROTOCOL_VERSION = 4;
3
3
  /** Default port the Persona API server listens on (user-configurable in the app). */
4
4
  export const DEFAULT_API_PORT = 25034;
5
5
  /** Default host clients dial: the server binds loopback unless LAN is opted in. */
6
6
  export const DEFAULT_API_HOST = '127.0.0.1';
7
+ /** Scene activation waits for asset preparation before committing the new scene. */
8
+ export const SCENE_ACTIVATION_TIMEOUT_MS = 120_000;
7
9
  /** Server close code: the session's API key was revoked. Terminal — the client must not redial. */
8
10
  export const CLOSE_KEY_REVOKED = 4001;
9
11
  /** Server close code: the user disconnected this session from Persona's settings. Terminal — the client must not redial. */
@@ -1,6 +1,22 @@
1
1
  import * as z from 'zod';
2
2
  import type { MethodName } from './methods.ts';
3
3
  import type { HotkeyConfig, ObjectContent } from './types.ts';
4
+ /** A complete transition replacement; scene.patch remains stage-owned for its other slices. */
5
+ export declare const SceneTransitionSchema: z.ZodObject<{
6
+ type: z.ZodEnum<{
7
+ circle: "circle";
8
+ image: "image";
9
+ video: "video";
10
+ cut: "cut";
11
+ fade: "fade";
12
+ wipe: "wipe";
13
+ }>;
14
+ durationMs: z.ZodNumber;
15
+ color: z.ZodString;
16
+ assetId: z.ZodNullable<z.ZodString>;
17
+ switchPoint: z.ZodNumber;
18
+ autoFade: z.ZodDefault<z.ZodBoolean>;
19
+ }, z.core.$strip>;
4
20
  export declare const InjectTargetSchema: z.ZodObject<{
5
21
  type: z.ZodEnum<{
6
22
  input: "input";
@@ -164,8 +180,8 @@ export declare const requestSchemas: {
164
180
  'hotkey.trigger': z.ZodObject<{
165
181
  hotkeyId: z.ZodString;
166
182
  }, z.core.$strip>;
167
- 'shortcut.trigger': z.ZodObject<{
168
- shortcutId: z.ZodString;
183
+ 'automation.run': z.ZodObject<{
184
+ automationId: z.ZodString;
169
185
  }, z.core.$strip>;
170
186
  'tracking.addSource': z.ZodObject<{
171
187
  kind: z.ZodEnum<{
@@ -1,15 +1,25 @@
1
1
  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
- import { SPEECH_URL_MAX_LENGTH, STORAGE_KEY_MAX_LENGTH, STORAGE_VALUE_MAX_LENGTH } from "../values/limits.js";
4
+ import { SCENE_COLOR_RE, SPEECH_URL_MAX_LENGTH, STORAGE_KEY_MAX_LENGTH, STORAGE_VALUE_MAX_LENGTH, } from "../values/limits.js";
5
5
  import { LIP_SYNC_CALIBRATION_ACTIONS, LIP_SYNC_GAIN_MAX, LIP_SYNC_MODES, LIP_SYNC_NOISE_GATE_MIN, LIP_SYNC_PHONEMES, LIP_SYNC_SMOOTHING_MAX, } from "../values/lipsync.js";
6
- import { ASSET_KINDS, POSE_SOURCE_IDS, TRACKING_SOURCE_IDS, TRACKING_SOURCE_KINDS } from "./types.js";
6
+ import { SCENE_TRANSITION_DURATION_MAX_MS, SCENE_TRANSITION_DURATION_MIN_MS, SCENE_TRANSITION_SWITCH_POINT_MAX, SCENE_TRANSITION_SWITCH_POINT_MIN, SCENE_TRANSITION_TYPES, } from "../values/scene-transition.js";
7
+ import { ASSET_KINDS, EFFECTS_QUALITY_LEVELS, INJECT_TARGET_TYPES, LIVE2D_ENGINES, MEDIAPIPE_DELEGATES, POSE_SOURCE_IDS, TRACKING_SOURCE_IDS, TRACKING_SOURCE_KINDS, } from "./types.js";
7
8
  // Runtime validation for the request side of the wire. Schemas exist for the
8
9
  // methods whose params the app's main process consumes directly; methods without
9
10
  // one are stage-owned — the renderer validates and heals them (same rules as the
10
11
  // panel). Fields marked z.custom are deliberately gated shallowly here because
11
12
  // the app heals them into shape server-side.
12
13
  const nonEmpty = z.string().min(1);
14
+ /** A complete transition replacement; scene.patch remains stage-owned for its other slices. */
15
+ export const SceneTransitionSchema = z.object({
16
+ type: z.enum(SCENE_TRANSITION_TYPES),
17
+ durationMs: z.number().min(SCENE_TRANSITION_DURATION_MIN_MS).max(SCENE_TRANSITION_DURATION_MAX_MS),
18
+ color: z.string().regex(SCENE_COLOR_RE),
19
+ assetId: nonEmpty.refine(v => v.trim() !== '', 'assetId must not be blank').nullable(),
20
+ switchPoint: z.number().min(SCENE_TRANSITION_SWITCH_POINT_MIN).max(SCENE_TRANSITION_SWITCH_POINT_MAX),
21
+ autoFade: z.boolean().default(false),
22
+ });
13
23
  const port = z.number().int().min(1).max(65535);
14
24
  const lipSyncCalibration = z.discriminatedUnion('action', [
15
25
  z.object({ action: z.enum(LIP_SYNC_CALIBRATION_ACTIONS) }),
@@ -28,10 +38,10 @@ const mediapipePatch = z.object({
28
38
  face: z.boolean().optional(),
29
39
  hands: z.boolean().optional(),
30
40
  body: z.boolean().optional(),
31
- delegate: z.enum(['CPU', 'GPU']).optional(),
41
+ delegate: z.enum(MEDIAPIPE_DELEGATES).optional(),
32
42
  });
33
43
  export const InjectTargetSchema = z.object({
34
- type: z.enum(['input', 'live2d-param', 'vrm-expression']),
44
+ type: z.enum(INJECT_TARGET_TYPES),
35
45
  id: nonEmpty,
36
46
  instanceId: nonEmpty.optional(),
37
47
  });
@@ -49,9 +59,9 @@ export const SettingsPatchSchema = z.object({
49
59
  showFps: z.boolean().optional(),
50
60
  fpsLimit: z.number().optional(),
51
61
  selectionOutline: z.boolean().optional(),
52
- effectsQuality: z.enum(['high', 'medium', 'low']).optional(),
62
+ effectsQuality: z.enum(EFFECTS_QUALITY_LEVELS).optional(),
53
63
  renderScale: z.number().optional(),
54
- live2dEngine: z.enum(['pixi', 'three']).optional(),
64
+ live2dEngine: z.enum(LIVE2D_ENGINES).optional(),
55
65
  })
56
66
  .optional(),
57
67
  });
@@ -114,7 +124,7 @@ export const requestSchemas = {
114
124
  config: z.custom(isRecord, 'config must be a hotkey config'),
115
125
  }),
116
126
  'hotkey.trigger': z.object({ hotkeyId: nonEmpty }),
117
- 'shortcut.trigger': z.object({ shortcutId: nonEmpty }),
127
+ 'automation.run': z.object({ automationId: nonEmpty }),
118
128
  'tracking.addSource': z.object({
119
129
  // Straight off the kind registry, for the same reason as ASSET_KINDS below: a schema
120
130
  // narrower than the constant answers invalid-params for a kind the app itself accepts.
@@ -1,5 +1,6 @@
1
1
  import type { ControllerConfig } from '../values/controller.ts';
2
- import type { EFFECT_SCOPES } from '../values/effect-schema.ts';
2
+ import type { EFFECT_BLEND_MODES, EFFECT_SCOPES } from '../values/effect-schema.ts';
3
+ import type { SCENE_TRANSITION_TYPES } from '../values/scene-transition.ts';
3
4
  import { type ArkitInputName } from '../values/arkit.ts';
4
5
  import { type BaseControllerInputName, type ControllerInputName, type ControllerMovementConfig } from '../values/controller.ts';
5
6
  import { type HandInputName } from '../values/hands.ts';
@@ -175,7 +176,8 @@ export interface SceneModelItem {
175
176
  /** MToon material fine-tuning, VRM only. */
176
177
  mtoon: MToonTuning;
177
178
  }
178
- export type ObjectSpace = '2d' | '3d';
179
+ export declare const OBJECT_SPACES: readonly ["2d", "3d"];
180
+ export type ObjectSpace = (typeof OBJECT_SPACES)[number];
179
181
  /** Where a webpage overlay renders relative to the stage. */
180
182
  export type WebLayer = 'behind' | 'front';
181
183
  export type CaptureKind = 'display' | 'window';
@@ -608,7 +610,7 @@ export interface SceneDroplets {
608
610
  glints: number;
609
611
  }
610
612
  /** Blend modes shared by Shoost's rim light and gradient. */
611
- export type EffectBlendMode = 'normal' | 'darken' | 'multiply' | 'colorBurn' | 'linearBurn' | 'add' | 'lighten' | 'screen' | 'colorDodge' | 'overlay' | 'softLight' | 'hardLight' | 'vividLight' | 'linearLight' | 'pinLight' | 'hardMix' | 'difference' | 'exclusion' | 'subtract' | 'divide' | 'hue' | 'saturation' | 'color' | 'luminosity';
613
+ export type EffectBlendMode = (typeof EFFECT_BLEND_MODES)[number];
612
614
  /** Solid, linear, or radial color overlay in scene or source coordinates. */
613
615
  export interface EffectGradient {
614
616
  enabled: boolean;
@@ -840,6 +842,19 @@ export interface SceneEnvironment {
840
842
  */
841
843
  effectLayers: ToggleEffectKey[];
842
844
  }
845
+ /** An effect played when this destination scene becomes active. */
846
+ export interface SceneTransition {
847
+ type: (typeof SCENE_TRANSITION_TYPES)[number];
848
+ /** Total animation time in milliseconds, 100–10,000; cuts are immediate. */
849
+ durationMs: number;
850
+ color: string;
851
+ /** A registered image/video id; filesystem paths never cross the wire. */
852
+ assetId: string | null;
853
+ /** Fraction of the animation where the scene changes, 0.05–0.95. */
854
+ switchPoint: number;
855
+ /** Fade a video's opacity at its start and end; false preserves the clip's authored alpha. */
856
+ autoFade: boolean;
857
+ }
843
858
  export interface Scene {
844
859
  id: string;
845
860
  name: string;
@@ -852,6 +867,8 @@ export interface Scene {
852
867
  /** Array order is display order only; live lights are keyed by id. */
853
868
  lights: SceneLight[];
854
869
  environment: SceneEnvironment;
870
+ /** Absent on older hosts; gate editing on the `scene-transitions` capability. */
871
+ transition?: SceneTransition;
855
872
  /** Electron accelerator that applies this scene, or null. */
856
873
  shortcut: string | null;
857
874
  }
@@ -871,12 +888,13 @@ export interface ScenePatch {
871
888
  vrmCamera?: SceneCamera;
872
889
  lights?: SceneLight[];
873
890
  environment?: SceneEnvironment;
891
+ transition?: SceneTransition;
874
892
  }
875
893
  /**
876
894
  * App-level features a client gates on (never version-sniff): `hello` and
877
895
  * `app.info` report them — the per-app mirror of {@link InstanceRuntime.capabilities}.
878
896
  */
879
- export declare const APP_CAPABILITIES: readonly ["storage", "speech", "shortcuts", "controllers", "model-editing", "asset-inspection", "layer-effects"];
897
+ export declare const APP_CAPABILITIES: readonly ["storage", "speech", "automations", "controllers", "model-editing", "asset-inspection", "layer-effects", "scene-transitions"];
880
898
  export type AppCapability = (typeof APP_CAPABILITIES)[number];
881
899
  export declare function isAppCapability(v: unknown): v is AppCapability;
882
900
  /** What a loaded model instance can do; absent capabilities answer `unsupported-for-format`. */
@@ -948,23 +966,27 @@ export interface HotkeyState extends HotkeyConfig {
948
966
  /** Hotkey ids currently registered with the OS (active model only). */
949
967
  registered: string[];
950
968
  }
951
- /** Action kinds an app shortcut can carry today; servers may send kinds newer than this list. */
952
- export declare const SHORTCUT_ACTION_KINDS: readonly ["effect-toggle", "effect-params", "camera-pose", "reset-camera", "layer-visibility", "stream-mode"];
953
- export type ShortcutActionKind = (typeof SHORTCUT_ACTION_KINDS)[number];
969
+ /** Action kinds an app automation can carry today; servers may send kinds newer than this list. */
970
+ export declare const AUTOMATION_ACTION_KINDS: readonly ["effect-toggle", "effect-params", "camera-pose", "reset-camera", "layer-visibility", "stream-mode", "delay"];
971
+ export type AutomationActionKind = (typeof AUTOMATION_ACTION_KINDS)[number];
954
972
  /**
955
- * One app-level global shortcut (a multi-action macro) as clients see it. Action
956
- * payloads stay app-side — `actionKinds` is what drives derived labels.
973
+ * One app automation as clients see it. Action payloads stay app-side — `actionKinds`
974
+ * drives derived labels.
957
975
  */
958
- export interface ShortcutInfo {
976
+ export interface AutomationInfo {
959
977
  id: string;
960
- /** User-given name, or null — derive a label from `actionKinds` (see `shortcutLabel`). */
978
+ /** User-given name, or null — derive a label from `actionKinds` (see `automationLabel`). */
961
979
  title: string | null;
962
- /** Bound key combo, or null for a trigger-only shortcut (`shortcut.trigger` still fires it). */
980
+ /** Bound key combo, or null when the automation has no keyboard/controller trigger. */
963
981
  accelerator: string | null;
964
982
  /** May include kinds newer than this SDK; label those generically. */
965
983
  actionKinds: string[];
966
984
  /** Whether the combo is currently registered with the OS. */
967
985
  registered: boolean;
986
+ /** Whether this automation can run. */
987
+ enabled: boolean;
988
+ /** Additional event trigger kinds. Trigger settings stay desktop-side. */
989
+ triggerKinds: string[];
968
990
  }
969
991
  export interface ExpressionPersistence {
970
992
  supported: boolean;
@@ -975,6 +997,8 @@ export interface ExpressionPersistence {
975
997
  export type JsonValue = string | number | boolean | null | JsonValue[] | {
976
998
  [key: string]: JsonValue;
977
999
  };
1000
+ export declare const LIVE2D_ENGINES: readonly ["pixi", "three"];
1001
+ export type Live2DEngine = (typeof LIVE2D_ENGINES)[number];
978
1002
  export declare const TRACKING_SOURCE_IDS: readonly ["persona-ios", "ifacialmocap", "vts-ios"];
979
1003
  export type TrackingSourceId = (typeof TRACKING_SOURCE_IDS)[number];
980
1004
  /** Body-pose protocols. Every one so far is UDP with a configurable port. */
@@ -985,17 +1009,18 @@ export type PoseStatus = 'off' | 'waiting' | 'tracking';
985
1009
  /** Every protocol a tracking source instance can speak; face and body kinds. */
986
1010
  export declare const TRACKING_SOURCE_KINDS: readonly ["persona-ios", "ifacialmocap", "vts-ios", "vmc", "mocopi", "mediapipe"];
987
1011
  export type TrackingSourceKind = (typeof TRACKING_SOURCE_KINDS)[number];
988
- export declare const TRACKING_CHANNELS: readonly ["face", "pose", "hands"];
989
- export type TrackingChannel = (typeof TRACKING_CHANNELS)[number];
1012
+ export type TrackingChannel = keyof typeof TRACKING_CHANNEL_FIELDS;
990
1013
  /** The scene-item binding each channel reads and writes. */
991
1014
  export declare const TRACKING_CHANNEL_FIELDS: {
992
1015
  readonly face: "faceSourceId";
993
1016
  readonly pose: "poseSourceId";
994
1017
  readonly hands: "handSourceId";
995
1018
  };
1019
+ export declare const TRACKING_CHANNELS: readonly TrackingChannel[];
996
1020
  export declare const HAND_TRACKING_MODES: readonly ["arms", "fingers"];
997
1021
  export type HandTrackingMode = (typeof HAND_TRACKING_MODES)[number];
998
1022
  export declare function isHandTrackingMode(v: unknown): v is HandTrackingMode;
1023
+ export declare const MEDIAPIPE_DELEGATES: readonly ["CPU", "GPU"];
999
1024
  /** The shared webcam source's enabled inference tasks and camera configuration. */
1000
1025
  export interface MediaPipeConfig {
1001
1026
  deviceId: string;
@@ -1003,7 +1028,7 @@ export interface MediaPipeConfig {
1003
1028
  face: boolean;
1004
1029
  hands: boolean;
1005
1030
  body: boolean;
1006
- delegate: 'CPU' | 'GPU';
1031
+ delegate: (typeof MEDIAPIPE_DELEGATES)[number];
1007
1032
  }
1008
1033
  export declare const DEFAULT_MEDIAPIPE_CONFIG: Readonly<MediaPipeConfig>;
1009
1034
  /** Whether a source kind uses a network face receiver. */
@@ -1088,7 +1113,7 @@ export interface Settings {
1088
1113
  effectsQuality: EffectsQuality;
1089
1114
  /** Absent on older hosts. */
1090
1115
  renderScale?: number;
1091
- live2dEngine?: 'pixi' | 'three';
1116
+ live2dEngine?: Live2DEngine;
1092
1117
  };
1093
1118
  /** `enabled` gates network face sources; `source` mirrors the first one's kind for old clients. */
1094
1119
  tracking: {
@@ -1118,12 +1143,43 @@ export interface SettingsPatch {
1118
1143
  selectionOutline?: boolean;
1119
1144
  effectsQuality?: EffectsQuality;
1120
1145
  renderScale?: number;
1121
- live2dEngine?: 'pixi' | 'three';
1146
+ live2dEngine?: Live2DEngine;
1122
1147
  };
1123
1148
  }
1124
- /** VTS's input vocabulary, plus `JawOpen` — the derived half of {@link INPUT_NAMES}. */
1125
- declare const VTS_INPUT_NAMES: readonly ["FaceAngleX", "FaceAngleY", "FaceAngleZ", "FacePositionX", "FacePositionY", "FacePositionZ", "EyeOpenLeft", "EyeOpenRight", "EyeLeftX", "EyeLeftY", "EyeRightX", "EyeRightY", "Brows", "BrowLeftY", "BrowRightY", "MouthSmile", "MouthOpen", "MouthX", "CheekPuff", "JawOpen", "TongueOut"];
1126
- type VtsInputName = (typeof VTS_INPUT_NAMES)[number];
1149
+ /**
1150
+ * From VTS's own registry (`FaceTrackingParamInfo.paramNameDictionary`), which is both the
1151
+ * range its editor seeds a new parameter with and what every `.vtube.json` was authored
1152
+ * against. Two families differ deliberately:
1153
+ *
1154
+ * - **the brow inputs** are signed here. VTS lists them `0..1`; we derive them as
1155
+ * `brow-up − brow-down`, so a frown needs the lower half.
1156
+ * - **`JawOpen`** is absent from VTS's registry — it exists there only as a plugin-created
1157
+ * parameter, which VTS then special-cases — so its span is the ARKit channel's.
1158
+ */
1159
+ declare const VTS_INPUT_RANGES: {
1160
+ readonly FaceAngleX: readonly [-30, 30];
1161
+ readonly FaceAngleY: readonly [-30, 30];
1162
+ readonly FaceAngleZ: readonly [-90, 90];
1163
+ readonly FacePositionX: readonly [-15, 15];
1164
+ readonly FacePositionY: readonly [-15, 15];
1165
+ readonly FacePositionZ: readonly [-10, 10];
1166
+ readonly EyeOpenLeft: readonly [0, 1];
1167
+ readonly EyeOpenRight: readonly [0, 1];
1168
+ readonly EyeLeftX: readonly [-1, 1];
1169
+ readonly EyeLeftY: readonly [-1, 1];
1170
+ readonly EyeRightX: readonly [-1, 1];
1171
+ readonly EyeRightY: readonly [-1, 1];
1172
+ readonly Brows: readonly [-1, 1];
1173
+ readonly BrowLeftY: readonly [-1, 1];
1174
+ readonly BrowRightY: readonly [-1, 1];
1175
+ readonly MouthSmile: readonly [0, 1];
1176
+ readonly MouthOpen: readonly [0, 1];
1177
+ readonly MouthX: readonly [-1, 1];
1178
+ readonly CheekPuff: readonly [0, 1];
1179
+ readonly JawOpen: readonly [0, 1];
1180
+ readonly TongueOut: readonly [0, 1];
1181
+ };
1182
+ type VtsInputName = keyof typeof VTS_INPUT_RANGES;
1127
1183
  /**
1128
1184
  * Default input vocabulary: face and hand inputs, raw ARKit channels and controller profile 1.
1129
1185
  * Additional controller profile ids are accepted by isInputName without appearing in this list.
@@ -1168,7 +1224,8 @@ export declare function getInputRange(name: InputName): readonly [number, number
1168
1224
  * - `vrm-expression` — reserved, not implemented yet; the server answers
1169
1225
  * `unsupported-for-format`.
1170
1226
  */
1171
- export type InjectTargetType = 'input' | 'live2d-param' | 'vrm-expression';
1227
+ export declare const INJECT_TARGET_TYPES: readonly ["input", "live2d-param", "vrm-expression"];
1228
+ export type InjectTargetType = (typeof INJECT_TARGET_TYPES)[number];
1172
1229
  export interface InjectTarget {
1173
1230
  type: InjectTargetType;
1174
1231
  id: string;