@laplace.live/persona-sdk 0.18.0 → 1.0.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.
Files changed (41) hide show
  1. package/README.md +1 -1
  2. package/dist/client/client.d.ts +1 -1
  3. package/dist/index.d.ts +7 -1
  4. package/dist/index.js +7 -1
  5. package/dist/values/bindings.d.ts +43 -0
  6. package/dist/values/bindings.js +1 -0
  7. package/dist/values/controller.d.ts +109 -0
  8. package/dist/values/controller.js +167 -0
  9. package/dist/values/curve.d.ts +7 -8
  10. package/dist/values/curve.js +18 -8
  11. package/dist/values/edit-history.d.ts +21 -0
  12. package/dist/values/edit-history.js +62 -0
  13. package/dist/values/effect-schema.d.ts +2 -2
  14. package/dist/values/effect-schema.js +1 -2
  15. package/dist/values/gltf-extensions.d.ts +20 -0
  16. package/dist/values/gltf-extensions.js +68 -0
  17. package/dist/values/guards.d.ts +2 -0
  18. package/dist/values/guards.js +5 -0
  19. package/dist/values/hotkeys.d.ts +6 -0
  20. package/dist/values/hotkeys.js +11 -0
  21. package/dist/values/labels.d.ts +2 -0
  22. package/dist/values/labels.js +5 -1
  23. package/dist/values/limits.d.ts +25 -0
  24. package/dist/values/limits.js +33 -0
  25. package/dist/values/locale.d.ts +2 -0
  26. package/dist/values/model-info.d.ts +66 -0
  27. package/dist/values/model-info.js +1 -0
  28. package/dist/values/stage-info.d.ts +27 -0
  29. package/dist/values/stage-info.js +1 -0
  30. package/dist/values/vrm-bindings.d.ts +14 -0
  31. package/dist/values/vrm-bindings.js +20 -0
  32. package/dist/wire/methods.d.ts +151 -5
  33. package/dist/wire/schemas.d.ts +46 -5
  34. package/dist/wire/schemas.js +12 -0
  35. package/dist/wire/types.d.ts +69 -58
  36. package/dist/wire/types.js +39 -11
  37. package/package.json +2 -16
  38. package/dist/effects.d.ts +0 -79
  39. package/dist/effects.js +0 -6
  40. package/dist/values/custom-effect.d.ts +0 -44
  41. package/dist/values/custom-effect.js +0 -136
package/dist/effects.js DELETED
@@ -1,6 +0,0 @@
1
- // The custom-effect authoring contract: what an effect module receives, what it
2
- // returns, and (re-exported) the manifest shape naming its params. Everything
3
- // touching three is type-only — the desktop hands the runtime to the module's
4
- // factory, because a module loaded from `persona://` can import nothing.
5
- // Typechecking against this entry needs `@types/three` (optional peer).
6
- export * from "./values/custom-effect.js";
@@ -1,44 +0,0 @@
1
- /** How wide a manifest may open a slider; keeps a typo'd range from making one unusable. */
2
- export declare const CUSTOM_EFFECT_PARAM_LIMIT = 1000000;
3
- /** Enabled custom effects one scene may compose — each costs a full-frame RTT. Disabled entries are uncapped. */
4
- export declare const CUSTOM_EFFECTS_MAX = 8;
5
- /** Params per effect. Past this the panel section stops being navigable. */
6
- export declare const CUSTOM_EFFECT_PARAM_MAX = 32;
7
- export type CustomEffectParamKind = 'number' | 'boolean' | 'color';
8
- /** One author-declared control. `kind` picks the panel widget and the healing rule. */
9
- export interface CustomEffectParam {
10
- kind: CustomEffectParamKind;
11
- /** Slider/field label. Author-supplied, so never translated. */
12
- label: string;
13
- /** Numbers: the clamp range and readout. Booleans and colors ignore these. */
14
- default: number | boolean | string;
15
- min?: number;
16
- max?: number;
17
- step?: number;
18
- digits?: number;
19
- unit?: string;
20
- }
21
- /** A validated `manifest.json`. */
22
- export interface CustomEffectManifest {
23
- name: string;
24
- /** Author-declared, shown in the panel's detail row. */
25
- version?: string;
26
- author?: string;
27
- description?: string;
28
- params: Record<string, CustomEffectParam>;
29
- }
30
- export declare function isCustomEffectSlug(v: unknown): v is string;
31
- /**
32
- * Validate a parsed `manifest.json`. Null when it carries no usable name —
33
- * everything else degrades (a bad param is dropped, not fatal), because a
34
- * half-typed manifest should still show the author what already works.
35
- */
36
- export declare function parseCustomEffectManifest(raw: unknown): CustomEffectManifest | null;
37
- /** Every declared param at its default — the params half of a fresh scene entry. */
38
- export declare function defaultCustomEffectParams(manifest: CustomEffectManifest): Record<string, number | boolean | string>;
39
- /**
40
- * Clamp saved params to the manifest that is installed now. Unknown keys are
41
- * kept: an author mid-edit who renames a param back should not find the value
42
- * gone, and a param costs nothing until the module reads it.
43
- */
44
- export declare function healCustomEffectParams(raw: unknown, manifest: CustomEffectManifest | null): Record<string, number | boolean | string>;
@@ -1,136 +0,0 @@
1
- // User-authored effects: the manifest contract and its validator.
2
- //
3
- // An effect folder holds `manifest.json` (plain data — this file's shape) and
4
- // `effect.js` (a TSL builder the stage worker evaluates). The split is what lets
5
- // main heal a scene's saved params without ever running author code: only the
6
- // worker imports the module, and it is the sole place third-party JS runs.
7
- //
8
- // Params mirror EffectParamSpec so the panel renders both kinds of effect with
9
- // the same sliders — but these arrive at runtime from disk, so everything here
10
- // validates rather than trusting the type.
11
- import { finiteOr, isFiniteNumber, isRecord, nonEmptyString } from "./guards.js";
12
- import { hexColorOr } from "./limits.js";
13
- /** How wide a manifest may open a slider; keeps a typo'd range from making one unusable. */
14
- export const CUSTOM_EFFECT_PARAM_LIMIT = 1e6;
15
- /** Enabled custom effects one scene may compose — each costs a full-frame RTT. Disabled entries are uncapped. */
16
- export const CUSTOM_EFFECTS_MAX = 8;
17
- /** Params per effect. Past this the panel section stops being navigable. */
18
- export const CUSTOM_EFFECT_PARAM_MAX = 32;
19
- /** Folder-name rule: lowercase, dash-separated. Also the on-disk path segment, so no dots or slashes. */
20
- const SLUG_RE = /^[a-z0-9][a-z0-9-]{0,63}$/;
21
- export function isCustomEffectSlug(v) {
22
- return typeof v === 'string' && SLUG_RE.test(v);
23
- }
24
- function bounded(v) {
25
- return Math.min(CUSTOM_EFFECT_PARAM_LIMIT, Math.max(-CUSTOM_EFFECT_PARAM_LIMIT, v));
26
- }
27
- function parseParam(raw) {
28
- if (!isRecord(raw))
29
- return null;
30
- const label = nonEmptyString(raw.label);
31
- if (label === null)
32
- return null;
33
- if (raw.kind === 'boolean')
34
- return { kind: 'boolean', label, default: raw.default === true };
35
- if (raw.kind === 'color')
36
- return { kind: 'color', label, default: hexColorOr(raw.default, '#ffffff') };
37
- // Numbers are the default kind: an omitted or unknown `kind` is far more often
38
- // a slider the author forgot to tag than a control they meant to drop.
39
- // Both ends clamp into ±LIMIT before ordering, or a range wholly past the
40
- // limit would keep one end beyond it.
41
- const lo = bounded(finiteOr(raw.min, 0));
42
- const hi = bounded(finiteOr(raw.max, 1));
43
- // An inverted or empty range would leave a slider that cannot move; widen to the default's own value.
44
- const min = Math.min(lo, hi);
45
- const max = Math.max(lo, hi);
46
- const def = Math.min(max, Math.max(min, finiteOr(raw.default, min)));
47
- const step = Math.min(max - min || 1, Math.abs(finiteOr(raw.step, 0.01)) || 0.01);
48
- return {
49
- kind: 'number',
50
- label,
51
- default: def,
52
- min,
53
- max,
54
- step,
55
- ...(isFiniteNumber(raw.digits) && { digits: Math.min(6, Math.max(0, Math.trunc(raw.digits))) }),
56
- ...(typeof raw.unit === 'string' && raw.unit !== '' && { unit: raw.unit.slice(0, 8) }),
57
- };
58
- }
59
- /**
60
- * Validate a parsed `manifest.json`. Null when it carries no usable name —
61
- * everything else degrades (a bad param is dropped, not fatal), because a
62
- * half-typed manifest should still show the author what already works.
63
- */
64
- export function parseCustomEffectManifest(raw) {
65
- if (!isRecord(raw))
66
- return null;
67
- const name = nonEmptyString(raw.name);
68
- if (name === null)
69
- return null;
70
- const params = {};
71
- if (isRecord(raw.params)) {
72
- for (const [key, value] of Object.entries(raw.params)) {
73
- if (Object.keys(params).length >= CUSTOM_EFFECT_PARAM_MAX)
74
- break;
75
- // The key is a JS identifier on the uniforms object the module builds; a
76
- // key it cannot name would silently never receive its value.
77
- if (!/^[A-Za-z_$][\w$]*$/.test(key))
78
- continue;
79
- const param = parseParam(value);
80
- if (param)
81
- params[key] = param;
82
- }
83
- }
84
- return {
85
- name: name.slice(0, 64),
86
- params,
87
- ...(typeof raw.version === 'string' && raw.version !== '' && { version: raw.version.slice(0, 32) }),
88
- ...(typeof raw.author === 'string' && raw.author !== '' && { author: raw.author.slice(0, 64) }),
89
- ...(typeof raw.description === 'string' &&
90
- raw.description !== '' && { description: raw.description.slice(0, 280) }),
91
- };
92
- }
93
- /** Every declared param at its default — the params half of a fresh scene entry. */
94
- export function defaultCustomEffectParams(manifest) {
95
- const out = {};
96
- for (const [key, param] of Object.entries(manifest.params))
97
- out[key] = param.default;
98
- return out;
99
- }
100
- /** A primitive a saved param may hold; non-finite numbers are junk, not tuning. */
101
- function isParamValue(v) {
102
- return isFiniteNumber(v) || typeof v === 'boolean' || typeof v === 'string';
103
- }
104
- /**
105
- * Clamp saved params to the manifest that is installed now. Unknown keys are
106
- * kept: an author mid-edit who renames a param back should not find the value
107
- * gone, and a param costs nothing until the module reads it.
108
- */
109
- export function healCustomEffectParams(raw, manifest) {
110
- const src = isRecord(raw) ? raw : {};
111
- const out = {};
112
- for (const [key, value] of Object.entries(src)) {
113
- const spec = manifest?.params[key];
114
- if (!spec) {
115
- // No spec to clamp against — an unknown key, or no manifest at all (effect
116
- // not installed on this machine); keeping primitives is what lets a
117
- // reinstall restore the user's tuning.
118
- if (isParamValue(value))
119
- out[key] = value;
120
- continue;
121
- }
122
- if (spec.kind === 'boolean')
123
- out[key] = typeof value === 'boolean' ? value : spec.default === true;
124
- else if (spec.kind === 'color')
125
- out[key] = hexColorOr(value, String(spec.default));
126
- else {
127
- const lo = spec.min ?? 0;
128
- const hi = spec.max ?? 1;
129
- out[key] = Math.min(hi, Math.max(lo, finiteOr(value, Number(spec.default))));
130
- }
131
- }
132
- if (manifest)
133
- for (const [key, spec] of Object.entries(manifest.params))
134
- out[key] ??= spec.default;
135
- return out;
136
- }