@hmcs/sdk 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.
- package/README.md +30 -0
- package/dist/app.cjs +63 -0
- package/dist/app.js +63 -0
- package/dist/assets.cjs +52 -0
- package/dist/assets.js +52 -0
- package/dist/audio.cjs +159 -0
- package/dist/audio.js +159 -0
- package/dist/commands.cjs +298 -0
- package/dist/commands.d.ts +852 -0
- package/dist/commands.js +296 -0
- package/dist/coordinates.cjs +69 -0
- package/dist/coordinates.js +69 -0
- package/dist/displays.cjs +38 -0
- package/dist/displays.js +38 -0
- package/dist/effects.cjs +50 -0
- package/dist/effects.js +50 -0
- package/dist/entities.cjs +249 -0
- package/dist/entities.js +249 -0
- package/dist/host.cjs +297 -0
- package/dist/host.js +294 -0
- package/dist/index.cjs +98 -0
- package/dist/index.d.ts +2612 -0
- package/dist/index.js +17 -0
- package/dist/mods.cjs +207 -0
- package/dist/mods.js +207 -0
- package/dist/preferences.cjs +90 -0
- package/dist/preferences.js +90 -0
- package/dist/settings.cjs +46 -0
- package/dist/settings.js +46 -0
- package/dist/shadowPanel.cjs +46 -0
- package/dist/shadowPanel.js +46 -0
- package/dist/signals.cjs +158 -0
- package/dist/signals.js +158 -0
- package/dist/speech.cjs +48 -0
- package/dist/speech.js +48 -0
- package/dist/utils.cjs +13 -0
- package/dist/utils.js +11 -0
- package/dist/vrm.cjs +469 -0
- package/dist/vrm.js +466 -0
- package/dist/webviews.cjs +310 -0
- package/dist/webviews.js +302 -0
- package/package.json +61 -0
|
@@ -0,0 +1,852 @@
|
|
|
1
|
+
import { ZodType } from 'zod';
|
|
2
|
+
import { EventSource } from 'eventsource';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Mathematical types and interfaces for 3D graphics and spatial calculations.
|
|
6
|
+
*
|
|
7
|
+
* This module provides type definitions for common mathematical concepts used
|
|
8
|
+
* throughout the Desktop Homunculus SDK, including transforms, vectors, and
|
|
9
|
+
* domain-specific request/response types.
|
|
10
|
+
* These types are designed to be compatible with Bevy's math system.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* // Working with transforms
|
|
15
|
+
* const transform: TransformArgs = {
|
|
16
|
+
* translation: [0, 100, 0],
|
|
17
|
+
* rotation: [0, 0, 0, 1],
|
|
18
|
+
* scale: [1, 1, 1]
|
|
19
|
+
* };
|
|
20
|
+
*
|
|
21
|
+
* // Working with vectors
|
|
22
|
+
* const position: Vec3 = [10, 20, 30];
|
|
23
|
+
* const screenPos: Vec2 = [1920, 1080];
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Represents a 3D transformation containing position, rotation, and scale.
|
|
28
|
+
*
|
|
29
|
+
* This is the core type for positioning objects in 3D space. All spatial
|
|
30
|
+
* operations in Desktop Homunculus use this transform representation,
|
|
31
|
+
* which is compatible with Bevy's Transform component.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* const identity: Transform = {
|
|
36
|
+
* translation: [0, 0, 0],
|
|
37
|
+
* rotation: [0, 0, 0, 1],
|
|
38
|
+
* scale: [1, 1, 1]
|
|
39
|
+
* };
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
interface Transform {
|
|
43
|
+
/**
|
|
44
|
+
* The position of the entity in world space.
|
|
45
|
+
* Format: [x, y, z] where Y is typically up in Bevy's coordinate system.
|
|
46
|
+
*/
|
|
47
|
+
translation: [number, number, number];
|
|
48
|
+
/**
|
|
49
|
+
* The rotation of the entity in world space, represented as a quaternion.
|
|
50
|
+
* Format: [x, y, z, w] where [0, 0, 0, 1] represents no rotation (identity).
|
|
51
|
+
*/
|
|
52
|
+
rotation: [number, number, number, number];
|
|
53
|
+
/**
|
|
54
|
+
* The scale of the entity in world space.
|
|
55
|
+
* Format: [x, y, z] where [1, 1, 1] represents normal size.
|
|
56
|
+
*/
|
|
57
|
+
scale: [number, number, number];
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Represents a 3D vector as [x, y, z].
|
|
61
|
+
* Used for 3D positions, directions, and mathematical calculations.
|
|
62
|
+
* Compatible with Bevy's Vec3 serialization format.
|
|
63
|
+
*/
|
|
64
|
+
type Vec3 = [number, number, number];
|
|
65
|
+
/**
|
|
66
|
+
* Represents a quaternion rotation as [x, y, z, w].
|
|
67
|
+
* Compatible with Bevy's Quat serialization format.
|
|
68
|
+
*/
|
|
69
|
+
type Quat = [number, number, number, number];
|
|
70
|
+
/** Transform arguments for API requests. Partial version of Transform. */
|
|
71
|
+
interface TransformArgs {
|
|
72
|
+
translation?: Vec3;
|
|
73
|
+
rotation?: Quat;
|
|
74
|
+
scale?: Vec3;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Global viewport coordinates (screen-space position) as [x, y]. */
|
|
78
|
+
type GlobalViewport = [number, number];
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Big Five personality traits (OCEAN model).
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* const ocean: Ocean = {
|
|
86
|
+
* openness: 0.8,
|
|
87
|
+
* conscientiousness: 0.6,
|
|
88
|
+
* extraversion: 0.7,
|
|
89
|
+
* };
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
interface Ocean {
|
|
93
|
+
/** Openness (0.0=conservative, 1.0=curious) */
|
|
94
|
+
openness?: number;
|
|
95
|
+
/** Conscientiousness (0.0=spontaneous, 1.0=organized) */
|
|
96
|
+
conscientiousness?: number;
|
|
97
|
+
/** Extraversion (0.0=introverted, 1.0=extroverted) */
|
|
98
|
+
extraversion?: number;
|
|
99
|
+
/** Agreeableness (0.0=independent, 1.0=cooperative) */
|
|
100
|
+
agreeableness?: number;
|
|
101
|
+
/** Neuroticism (0.0=stable, 1.0=sensitive) */
|
|
102
|
+
neuroticism?: number;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Persona data for a VRM character.
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```typescript
|
|
109
|
+
* const persona: Persona = {
|
|
110
|
+
* profile: "A cheerful virtual assistant",
|
|
111
|
+
* personality: "Friendly and helpful",
|
|
112
|
+
* ocean: { openness: 0.8, extraversion: 0.7 },
|
|
113
|
+
* metadata: {},
|
|
114
|
+
* };
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
interface Persona {
|
|
118
|
+
/** Character profile/background description. */
|
|
119
|
+
profile: string;
|
|
120
|
+
/** Personality description in natural language. */
|
|
121
|
+
personality?: string | null;
|
|
122
|
+
/** Big Five personality parameters. */
|
|
123
|
+
ocean: Ocean;
|
|
124
|
+
/** Extension metadata for MODs. */
|
|
125
|
+
metadata: Record<string, unknown>;
|
|
126
|
+
}
|
|
127
|
+
/** Override type for expression override settings. */
|
|
128
|
+
type OverrideType = "none" | "blend" | "block";
|
|
129
|
+
/**
|
|
130
|
+
* Information about a single VRM expression.
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```typescript
|
|
134
|
+
* const vrm = await Vrm.findByName("MyAvatar");
|
|
135
|
+
* const { expressions } = await vrm.expressions();
|
|
136
|
+
* for (const expr of expressions) {
|
|
137
|
+
* console.log(`${expr.name}: weight=${expr.weight}, binary=${expr.isBinary}`);
|
|
138
|
+
* }
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
interface ExpressionInfo {
|
|
142
|
+
/** Expression name (e.g. "happy", "aa", "blink"). */
|
|
143
|
+
name: string;
|
|
144
|
+
/** Current weight value (0.0-1.0). */
|
|
145
|
+
weight: number;
|
|
146
|
+
/** Whether this expression is binary (snaps to 0 or 1). */
|
|
147
|
+
isBinary: boolean;
|
|
148
|
+
/** Override type for blink expressions. */
|
|
149
|
+
overrideBlink: OverrideType;
|
|
150
|
+
/** Override type for lookAt expressions. */
|
|
151
|
+
overrideLookAt: OverrideType;
|
|
152
|
+
/** Override type for mouth expressions. */
|
|
153
|
+
overrideMouth: OverrideType;
|
|
154
|
+
}
|
|
155
|
+
/** Response for VRM expression queries. */
|
|
156
|
+
interface ExpressionsResponse {
|
|
157
|
+
expressions: ExpressionInfo[];
|
|
158
|
+
}
|
|
159
|
+
/** Spring bone physics properties. */
|
|
160
|
+
interface SpringBoneProps {
|
|
161
|
+
stiffness: number;
|
|
162
|
+
dragForce: number;
|
|
163
|
+
gravityPower: number;
|
|
164
|
+
gravityDir: [number, number, number];
|
|
165
|
+
hitRadius: number;
|
|
166
|
+
}
|
|
167
|
+
/** A single spring bone chain. */
|
|
168
|
+
interface SpringBoneChain {
|
|
169
|
+
entity: number;
|
|
170
|
+
joints: string[];
|
|
171
|
+
props: SpringBoneProps;
|
|
172
|
+
}
|
|
173
|
+
/** Response for spring bone chains query. */
|
|
174
|
+
interface SpringBoneChainsResponse {
|
|
175
|
+
chains: SpringBoneChain[];
|
|
176
|
+
}
|
|
177
|
+
/** Repeat settings for VRMA playback. */
|
|
178
|
+
interface VrmaRepeat {
|
|
179
|
+
type: "forever" | "never" | "count";
|
|
180
|
+
count?: number;
|
|
181
|
+
}
|
|
182
|
+
/** Request body for playing a VRMA animation. */
|
|
183
|
+
interface VrmaPlayRequest {
|
|
184
|
+
asset: string;
|
|
185
|
+
transitionSecs?: number;
|
|
186
|
+
repeat?: VrmaRepeat;
|
|
187
|
+
waitForCompletion?: boolean;
|
|
188
|
+
/** If true, resets SpringBone velocities to prevent bouncing during animation transitions. */
|
|
189
|
+
resetSpringBones?: boolean;
|
|
190
|
+
}
|
|
191
|
+
/** State of a VRMA animation. */
|
|
192
|
+
interface VrmaState {
|
|
193
|
+
playing: boolean;
|
|
194
|
+
repeat: string;
|
|
195
|
+
speed: number;
|
|
196
|
+
elapsedSecs: number;
|
|
197
|
+
}
|
|
198
|
+
/** Info about a VRMA animation entity. */
|
|
199
|
+
interface VrmaInfo {
|
|
200
|
+
entity: number;
|
|
201
|
+
name: string;
|
|
202
|
+
playing: boolean;
|
|
203
|
+
}
|
|
204
|
+
/** Current look-at state of a VRM. */
|
|
205
|
+
type LookAtState = {
|
|
206
|
+
type: "cursor";
|
|
207
|
+
} | {
|
|
208
|
+
type: "target";
|
|
209
|
+
entity: number;
|
|
210
|
+
};
|
|
211
|
+
/**
|
|
212
|
+
* Snapshot of a VRM instance with full runtime state.
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* ```typescript
|
|
216
|
+
* const snapshots = await Vrm.findAllDetailed();
|
|
217
|
+
* for (const s of snapshots) {
|
|
218
|
+
* console.log(`${s.name}: ${s.state} at (${s.globalViewport?.[0]}, ${s.globalViewport?.[1]})`);
|
|
219
|
+
* }
|
|
220
|
+
* ```
|
|
221
|
+
*/
|
|
222
|
+
interface VrmSnapshot {
|
|
223
|
+
entity: number;
|
|
224
|
+
name: string;
|
|
225
|
+
state: string;
|
|
226
|
+
transform: Transform;
|
|
227
|
+
globalViewport: GlobalViewport | null;
|
|
228
|
+
expressions: ExpressionsResponse;
|
|
229
|
+
animations: VrmaInfo[];
|
|
230
|
+
lookAt: LookAtState | null;
|
|
231
|
+
linkedWebviews: number[];
|
|
232
|
+
persona: Persona;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Response from the VRM position endpoint.
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* ```ts
|
|
239
|
+
* const vrm = await Vrm.findByName("MyCharacter");
|
|
240
|
+
* const pos = await vrm.position();
|
|
241
|
+
* console.log(`Screen: (${pos.globalViewport?.[0]}, ${pos.globalViewport?.[1]})`);
|
|
242
|
+
* console.log(`World: (${pos.world[0]}, ${pos.world[1]}, ${pos.world[2]})`);
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
interface PositionResponse {
|
|
246
|
+
/** Global screen coordinates (multi-monitor origin at leftmost screen). Null if not visible. */
|
|
247
|
+
globalViewport: GlobalViewport | null;
|
|
248
|
+
/** Bevy world coordinates. */
|
|
249
|
+
world: Vec3;
|
|
250
|
+
}
|
|
251
|
+
interface SpawnVrmOptions {
|
|
252
|
+
transform?: TransformArgs;
|
|
253
|
+
persona?: Persona;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* A single keyframe in a speech timeline.
|
|
257
|
+
*/
|
|
258
|
+
interface TimelineKeyframe {
|
|
259
|
+
/**
|
|
260
|
+
* Duration of this keyframe in seconds.
|
|
261
|
+
*/
|
|
262
|
+
duration: number;
|
|
263
|
+
/**
|
|
264
|
+
* Expression targets to set during this keyframe.
|
|
265
|
+
* Keys are expression names (e.g. "aa", "ih", "happy"), values are weights (0.0-1.0).
|
|
266
|
+
*/
|
|
267
|
+
targets?: Record<string, number>;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Options for the timeline speech API.
|
|
271
|
+
*/
|
|
272
|
+
interface SpeakTimelineOptions {
|
|
273
|
+
/**
|
|
274
|
+
* If true, the method will wait for the speech to complete.
|
|
275
|
+
* Defaults to true.
|
|
276
|
+
*/
|
|
277
|
+
waitForCompletion?: boolean;
|
|
278
|
+
/**
|
|
279
|
+
* Duration in seconds for smoothstep blending between adjacent keyframes.
|
|
280
|
+
* Defaults to 0.05 (50ms). Clamped to 40% of each keyframe's duration.
|
|
281
|
+
*/
|
|
282
|
+
transitionDuration?: number;
|
|
283
|
+
}
|
|
284
|
+
interface VrmPointerEvent {
|
|
285
|
+
/**
|
|
286
|
+
* The cursor position in the global viewport.
|
|
287
|
+
*/
|
|
288
|
+
globalViewport: [number, number];
|
|
289
|
+
}
|
|
290
|
+
interface VrmDragEvent extends VrmPointerEvent {
|
|
291
|
+
/**
|
|
292
|
+
* The change in cursor position since the last event.
|
|
293
|
+
*/
|
|
294
|
+
delta: [number, number];
|
|
295
|
+
}
|
|
296
|
+
type Button = "Primary" | "Secondary" | "Middle";
|
|
297
|
+
interface VrmMouseEvent extends VrmPointerEvent {
|
|
298
|
+
/**
|
|
299
|
+
* The button that was pressed or released.
|
|
300
|
+
*/
|
|
301
|
+
button: Button;
|
|
302
|
+
}
|
|
303
|
+
interface VrmStateChangeEvent {
|
|
304
|
+
/**
|
|
305
|
+
* The new state of the VRM.
|
|
306
|
+
*/
|
|
307
|
+
state: string;
|
|
308
|
+
}
|
|
309
|
+
interface PersonaChangeEvent {
|
|
310
|
+
/**
|
|
311
|
+
* The updated persona.
|
|
312
|
+
*/
|
|
313
|
+
persona: Persona;
|
|
314
|
+
}
|
|
315
|
+
type EventMap = {
|
|
316
|
+
"drag-start": VrmPointerEvent;
|
|
317
|
+
"drag": VrmDragEvent;
|
|
318
|
+
"drag-end": VrmPointerEvent;
|
|
319
|
+
"pointer-press": VrmMouseEvent;
|
|
320
|
+
"pointer-click": VrmMouseEvent;
|
|
321
|
+
"pointer-release": VrmMouseEvent;
|
|
322
|
+
"pointer-over": VrmPointerEvent;
|
|
323
|
+
"pointer-out": VrmPointerEvent;
|
|
324
|
+
"pointer-cancel": VrmPointerEvent;
|
|
325
|
+
"pointer-move": VrmPointerEvent;
|
|
326
|
+
"state-change": VrmStateChangeEvent;
|
|
327
|
+
"expression-change": VrmStateChangeEvent;
|
|
328
|
+
"vrma-play": VrmStateChangeEvent;
|
|
329
|
+
"vrma-finish": VrmStateChangeEvent;
|
|
330
|
+
"persona-change": PersonaChangeEvent;
|
|
331
|
+
};
|
|
332
|
+
interface VrmMetadata {
|
|
333
|
+
name: string;
|
|
334
|
+
entity: number;
|
|
335
|
+
}
|
|
336
|
+
type Bones = "hips" | "spine" | "chest" | "neck" | "head" | "leftShoulder" | "leftArm" | "leftForeArm" | "leftHand" | "rightShoulder" | "rightArm" | "rightForeArm" | "rightHand" | "leftUpLeg" | "leftLeg" | "leftFoot" | "rightUpLeg" | "rightLeg" | "rightFoot";
|
|
337
|
+
declare class VrmEventSource implements Disposable {
|
|
338
|
+
readonly eventSource: EventSource;
|
|
339
|
+
constructor(eventSource: EventSource);
|
|
340
|
+
/**
|
|
341
|
+
* Registers an event listener for the specified event type.
|
|
342
|
+
*/
|
|
343
|
+
on<K extends keyof EventMap>(event: K, callback: (event: EventMap[K]) => (void | Promise<void>)): void;
|
|
344
|
+
/**
|
|
345
|
+
* Closes the EventSource connection.
|
|
346
|
+
*/
|
|
347
|
+
close(): void;
|
|
348
|
+
[Symbol.dispose](): void;
|
|
349
|
+
}
|
|
350
|
+
declare class Vrm {
|
|
351
|
+
readonly entity: number;
|
|
352
|
+
constructor(entity: number);
|
|
353
|
+
/**
|
|
354
|
+
* Returns an EventSource for receiving events related to this VRM entity.
|
|
355
|
+
*/
|
|
356
|
+
events(): VrmEventSource;
|
|
357
|
+
/**
|
|
358
|
+
* Returns the current state of the VRM.
|
|
359
|
+
*/
|
|
360
|
+
state(): Promise<string>;
|
|
361
|
+
/**
|
|
362
|
+
* Sets the state of the VRM.
|
|
363
|
+
*
|
|
364
|
+
* @param state The new state to set.
|
|
365
|
+
*/
|
|
366
|
+
setState(state: string): Promise<void>;
|
|
367
|
+
/**
|
|
368
|
+
* Returns the persona of the VRM.
|
|
369
|
+
*
|
|
370
|
+
* @example
|
|
371
|
+
* ```typescript
|
|
372
|
+
* const vrm = await Vrm.findByName("MyAvatar");
|
|
373
|
+
* const persona = await vrm.persona();
|
|
374
|
+
* console.log(persona.profile);
|
|
375
|
+
* ```
|
|
376
|
+
*/
|
|
377
|
+
persona(): Promise<Persona>;
|
|
378
|
+
/**
|
|
379
|
+
* Sets the persona of the VRM.
|
|
380
|
+
*
|
|
381
|
+
* @param persona The persona data to set.
|
|
382
|
+
*
|
|
383
|
+
* @example
|
|
384
|
+
* ```typescript
|
|
385
|
+
* const vrm = await Vrm.findByName("MyAvatar");
|
|
386
|
+
* await vrm.setPersona({
|
|
387
|
+
* profile: "A cheerful assistant",
|
|
388
|
+
* ocean: { openness: 0.8, extraversion: 0.7 },
|
|
389
|
+
* metadata: {},
|
|
390
|
+
* });
|
|
391
|
+
* ```
|
|
392
|
+
*/
|
|
393
|
+
setPersona(persona: Persona): Promise<void>;
|
|
394
|
+
/**
|
|
395
|
+
* Returns the name of the VRM avatar.
|
|
396
|
+
*/
|
|
397
|
+
name(): Promise<string>;
|
|
398
|
+
/**
|
|
399
|
+
* Finds the entity ID of a bone by its name.
|
|
400
|
+
*/
|
|
401
|
+
findBoneEntity(bone: Bones): Promise<number>;
|
|
402
|
+
/**
|
|
403
|
+
* Despawns this VRM entity.
|
|
404
|
+
*/
|
|
405
|
+
despawn(): Promise<void>;
|
|
406
|
+
/**
|
|
407
|
+
* Gets the current position of this VRM in both screen and world coordinates.
|
|
408
|
+
*
|
|
409
|
+
* @example
|
|
410
|
+
* ```ts
|
|
411
|
+
* const vrm = await Vrm.findByName("MyCharacter");
|
|
412
|
+
* const pos = await vrm.position();
|
|
413
|
+
* console.log(`Screen: (${pos.globalViewport?.[0]}, ${pos.globalViewport?.[1]})`);
|
|
414
|
+
* console.log(`World: (${pos.world[0]}, ${pos.world[1]}, ${pos.world[2]})`);
|
|
415
|
+
* ```
|
|
416
|
+
*/
|
|
417
|
+
position(): Promise<PositionResponse>;
|
|
418
|
+
/**
|
|
419
|
+
* Gets all expressions and their current weights, including metadata
|
|
420
|
+
* such as binary status and override settings.
|
|
421
|
+
*
|
|
422
|
+
* @example
|
|
423
|
+
* ```typescript
|
|
424
|
+
* const vrm = await Vrm.findByName("MyAvatar");
|
|
425
|
+
* const { expressions } = await vrm.expressions();
|
|
426
|
+
* for (const expr of expressions) {
|
|
427
|
+
* console.log(`${expr.name}: ${expr.weight}`);
|
|
428
|
+
* }
|
|
429
|
+
* ```
|
|
430
|
+
*/
|
|
431
|
+
expressions(): Promise<ExpressionsResponse>;
|
|
432
|
+
/**
|
|
433
|
+
* Sets expression weights, replacing all previous overrides.
|
|
434
|
+
* Expressions not included will return to VRMA animation control.
|
|
435
|
+
*
|
|
436
|
+
* @param weights A record of expression names to weight values (0.0-1.0).
|
|
437
|
+
*
|
|
438
|
+
* @example
|
|
439
|
+
* ```typescript
|
|
440
|
+
* const vrm = await Vrm.findByName("MyAvatar");
|
|
441
|
+
* await vrm.setExpressions({ happy: 1.0, blink: 0.5 });
|
|
442
|
+
* ```
|
|
443
|
+
*/
|
|
444
|
+
setExpressions(weights: Record<string, number>): Promise<void>;
|
|
445
|
+
/**
|
|
446
|
+
* Modifies specific expression weights without affecting others (partial update).
|
|
447
|
+
* Existing overrides not mentioned remain unchanged.
|
|
448
|
+
*
|
|
449
|
+
* @param weights A record of expression names to weight values (0.0-1.0).
|
|
450
|
+
*
|
|
451
|
+
* @example
|
|
452
|
+
* ```typescript
|
|
453
|
+
* const vrm = await Vrm.findByName("MyAvatar");
|
|
454
|
+
* // Only modifies "happy", leaves other overrides intact
|
|
455
|
+
* await vrm.modifyExpressions({ happy: 1.0 });
|
|
456
|
+
* ```
|
|
457
|
+
*/
|
|
458
|
+
modifyExpressions(weights: Record<string, number>): Promise<void>;
|
|
459
|
+
/**
|
|
460
|
+
* Clears all expression overrides, returning control to VRMA animation.
|
|
461
|
+
*
|
|
462
|
+
* @example
|
|
463
|
+
* ```typescript
|
|
464
|
+
* const vrm = await Vrm.findByName("MyAvatar");
|
|
465
|
+
* await vrm.clearExpressions();
|
|
466
|
+
* ```
|
|
467
|
+
*/
|
|
468
|
+
clearExpressions(): Promise<void>;
|
|
469
|
+
/**
|
|
470
|
+
* Modifies mouth expression weights for lip-sync.
|
|
471
|
+
* Unspecified mouth expressions are reset to 0.0.
|
|
472
|
+
* Non-mouth expression overrides are preserved.
|
|
473
|
+
*
|
|
474
|
+
* @param weights A record of mouth expression names to weight values (0.0-1.0).
|
|
475
|
+
*
|
|
476
|
+
* @example
|
|
477
|
+
* ```typescript
|
|
478
|
+
* const vrm = await Vrm.findByName("MyAvatar");
|
|
479
|
+
* await vrm.modifyMouth({ aa: 0.8, oh: 0.2 });
|
|
480
|
+
* ```
|
|
481
|
+
*/
|
|
482
|
+
modifyMouth(weights: Record<string, number>): Promise<void>;
|
|
483
|
+
/**
|
|
484
|
+
* Gets all spring bone chains.
|
|
485
|
+
*/
|
|
486
|
+
springBones(): Promise<SpringBoneChainsResponse>;
|
|
487
|
+
/**
|
|
488
|
+
* Gets a single spring bone chain by entity ID.
|
|
489
|
+
*
|
|
490
|
+
* @param chainId The chain entity ID.
|
|
491
|
+
*/
|
|
492
|
+
springBone(chainId: number): Promise<SpringBoneChain>;
|
|
493
|
+
/**
|
|
494
|
+
* Updates spring bone properties for a chain.
|
|
495
|
+
*
|
|
496
|
+
* @param chainId The chain entity ID.
|
|
497
|
+
* @param props Partial properties to update.
|
|
498
|
+
*/
|
|
499
|
+
setSpringBone(chainId: number, props: Partial<SpringBoneProps>): Promise<void>;
|
|
500
|
+
/**
|
|
501
|
+
* Gets all VRMA animations for this VRM.
|
|
502
|
+
*/
|
|
503
|
+
listVrma(): Promise<VrmaInfo[]>;
|
|
504
|
+
/**
|
|
505
|
+
* Plays a VRMA animation.
|
|
506
|
+
*
|
|
507
|
+
* @param options Play request options including asset, repeat, transition.
|
|
508
|
+
*/
|
|
509
|
+
playVrma(options: VrmaPlayRequest): Promise<void>;
|
|
510
|
+
/**
|
|
511
|
+
* Stops a VRMA animation.
|
|
512
|
+
*
|
|
513
|
+
* @param asset The asset ID of the VRMA animation to stop.
|
|
514
|
+
*/
|
|
515
|
+
stopVrma(asset: string): Promise<void>;
|
|
516
|
+
/**
|
|
517
|
+
* Gets the state of a VRMA animation.
|
|
518
|
+
*
|
|
519
|
+
* @param asset The asset ID of the VRMA animation to query.
|
|
520
|
+
*/
|
|
521
|
+
vrmaState(asset: string): Promise<VrmaState>;
|
|
522
|
+
/**
|
|
523
|
+
* Sets the playback speed of a VRMA animation.
|
|
524
|
+
*
|
|
525
|
+
* @param asset The asset ID of the VRMA animation.
|
|
526
|
+
* @param speed The playback speed.
|
|
527
|
+
*/
|
|
528
|
+
setVrmaSpeed(asset: string, speed: number): Promise<void>;
|
|
529
|
+
/**
|
|
530
|
+
* Speaks using pre-generated audio with a timeline of expression keyframes.
|
|
531
|
+
* This allows any TTS engine to be used — the engine receives WAV audio and
|
|
532
|
+
* frame-synchronized lip-sync data.
|
|
533
|
+
*
|
|
534
|
+
* @param audio - WAV audio data as ArrayBuffer or Uint8Array.
|
|
535
|
+
* @param keyframes - Timeline keyframes specifying expression targets and durations.
|
|
536
|
+
* @param options - Optional settings (e.g. waitForCompletion).
|
|
537
|
+
*
|
|
538
|
+
* @example
|
|
539
|
+
* ```typescript
|
|
540
|
+
* const vrm = await Vrm.findByName("MyAvatar");
|
|
541
|
+
* const wavData = await fetchWavFromTTS("Hello world");
|
|
542
|
+
* await vrm.speakWithTimeline(wavData, [
|
|
543
|
+
* { duration: 0.1, targets: { aa: 1.0 } },
|
|
544
|
+
* { duration: 0.05 },
|
|
545
|
+
* { duration: 0.12, targets: { oh: 1.0, happy: 0.5 } },
|
|
546
|
+
* ]);
|
|
547
|
+
* ```
|
|
548
|
+
*/
|
|
549
|
+
speakWithTimeline(audio: ArrayBuffer | Uint8Array, keyframes: TimelineKeyframe[], options?: SpeakTimelineOptions): Promise<void>;
|
|
550
|
+
/**
|
|
551
|
+
* Looks at the mouse cursor.
|
|
552
|
+
*/
|
|
553
|
+
lookAtCursor(): Promise<void>;
|
|
554
|
+
/**
|
|
555
|
+
* Sets the VRM's look-at target to a specific entity.
|
|
556
|
+
*
|
|
557
|
+
* @param target The entity ID to look at.
|
|
558
|
+
*/
|
|
559
|
+
lookAtTarget(target: number): Promise<void>;
|
|
560
|
+
/**
|
|
561
|
+
* Disables the VRM's look-at functionality.
|
|
562
|
+
*/
|
|
563
|
+
unlook(): Promise<void>;
|
|
564
|
+
/**
|
|
565
|
+
* Spawns a new VRM instance from the given mod asset ID.
|
|
566
|
+
*/
|
|
567
|
+
static spawn(asset: string, options?: SpawnVrmOptions): Promise<Vrm>;
|
|
568
|
+
/**
|
|
569
|
+
* Finds a VRM instance by its name.
|
|
570
|
+
*
|
|
571
|
+
* @param vrmName VRM avatar name
|
|
572
|
+
*/
|
|
573
|
+
static findByName(vrmName: string): Promise<Vrm>;
|
|
574
|
+
/**
|
|
575
|
+
* Waits for a VRM instance to be spawned and initialized by its name.
|
|
576
|
+
*
|
|
577
|
+
* @param vrmName VRM avatar name
|
|
578
|
+
*/
|
|
579
|
+
static waitLoadByName(vrmName: string): Promise<Vrm>;
|
|
580
|
+
/**
|
|
581
|
+
* Returns entity IDs of all currently loaded VRM instances.
|
|
582
|
+
*
|
|
583
|
+
* @example
|
|
584
|
+
* ```typescript
|
|
585
|
+
* const entities = await Vrm.findAllEntities();
|
|
586
|
+
* console.log(`Found ${entities.length} VRM entities`);
|
|
587
|
+
* ```
|
|
588
|
+
*/
|
|
589
|
+
static findAllEntities(): Promise<number[]>;
|
|
590
|
+
/**
|
|
591
|
+
* Returns detailed snapshot of all VRM instances.
|
|
592
|
+
*
|
|
593
|
+
* @example
|
|
594
|
+
* ```typescript
|
|
595
|
+
* const snapshots = await Vrm.findAllDetailed();
|
|
596
|
+
* for (const s of snapshots) {
|
|
597
|
+
* console.log(`${s.name}: ${s.state} at (${s.globalViewport?.[0]}, ${s.globalViewport?.[1]})`);
|
|
598
|
+
* }
|
|
599
|
+
* ```
|
|
600
|
+
*/
|
|
601
|
+
static findAllDetailed(): Promise<VrmSnapshot[]>;
|
|
602
|
+
static streamMetadata(f: (vrm: VrmMetadata) => (void | Promise<void>)): EventSource;
|
|
603
|
+
/**
|
|
604
|
+
* Streams all currently existing VRM instances and any VRM instances that will be created in the future.
|
|
605
|
+
* @param f
|
|
606
|
+
*/
|
|
607
|
+
static stream(f: (vrm: Vrm) => (void | Promise<void>)): EventSource;
|
|
608
|
+
/**
|
|
609
|
+
* Returns all VRM instances that are currently loaded.
|
|
610
|
+
*/
|
|
611
|
+
static findAll(): Promise<Vrm[]>;
|
|
612
|
+
private fetch;
|
|
613
|
+
private post;
|
|
614
|
+
private put;
|
|
615
|
+
private patch;
|
|
616
|
+
private delete;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* Command script utilities for Desktop Homunculus mods.
|
|
621
|
+
*
|
|
622
|
+
* This module provides helpers for parsing stdin input and writing structured
|
|
623
|
+
* output in mod command scripts (`bin/` scripts invoked via the HTTP command
|
|
624
|
+
* execution API).
|
|
625
|
+
*
|
|
626
|
+
* **Input:** {@link input.parse} / {@link input.parseMenu} / {@link input.read}
|
|
627
|
+
* **Output:** {@link output.succeed} / {@link output.fail} / {@link output.write} / {@link output.writeError}
|
|
628
|
+
*
|
|
629
|
+
* @remarks
|
|
630
|
+
* This module uses Node.js APIs (`process.stdin`, `fs.writeFileSync`) and is
|
|
631
|
+
* not browser-compatible. Import from `@hmcs/sdk/commands` — it is intentionally
|
|
632
|
+
* not re-exported from the main `@hmcs/sdk` entry point.
|
|
633
|
+
*
|
|
634
|
+
* @example
|
|
635
|
+
* ```typescript
|
|
636
|
+
* import { z } from "zod";
|
|
637
|
+
* import { input, output, StdinParseError } from "@hmcs/sdk/commands";
|
|
638
|
+
*
|
|
639
|
+
* const schema = z.object({ name: z.string() });
|
|
640
|
+
*
|
|
641
|
+
* try {
|
|
642
|
+
* const data = await input.parse(schema);
|
|
643
|
+
* output.succeed({ greeting: `Hello, ${data.name}!` });
|
|
644
|
+
* } catch (err) {
|
|
645
|
+
* output.fail("GREET_FAILED", (err as Error).message);
|
|
646
|
+
* }
|
|
647
|
+
* ```
|
|
648
|
+
*
|
|
649
|
+
* @packageDocumentation
|
|
650
|
+
*/
|
|
651
|
+
|
|
652
|
+
/**
|
|
653
|
+
* Error thrown by {@link input.parse} when stdin is empty, contains invalid JSON,
|
|
654
|
+
* or fails Zod schema validation.
|
|
655
|
+
*
|
|
656
|
+
* @example
|
|
657
|
+
* ```typescript
|
|
658
|
+
* import { input, StdinParseError } from "@hmcs/sdk/commands";
|
|
659
|
+
*
|
|
660
|
+
* try {
|
|
661
|
+
* const data = await input.parse(schema);
|
|
662
|
+
* } catch (err) {
|
|
663
|
+
* if (err instanceof StdinParseError) {
|
|
664
|
+
* console.error(JSON.stringify({ code: err.code, message: err.message }));
|
|
665
|
+
* process.exit(1);
|
|
666
|
+
* }
|
|
667
|
+
* throw err;
|
|
668
|
+
* }
|
|
669
|
+
* ```
|
|
670
|
+
*/
|
|
671
|
+
declare class StdinParseError extends Error {
|
|
672
|
+
/** Structured error code identifying the failure stage. */
|
|
673
|
+
readonly code: "EMPTY_STDIN" | "INVALID_JSON" | "VALIDATION_ERROR";
|
|
674
|
+
/** For `VALIDATION_ERROR`, contains the `ZodError` instance. */
|
|
675
|
+
readonly details?: unknown | undefined;
|
|
676
|
+
readonly name = "StdinParseError";
|
|
677
|
+
constructor(
|
|
678
|
+
/** Structured error code identifying the failure stage. */
|
|
679
|
+
code: "EMPTY_STDIN" | "INVALID_JSON" | "VALIDATION_ERROR", message: string,
|
|
680
|
+
/** For `VALIDATION_ERROR`, contains the `ZodError` instance. */
|
|
681
|
+
details?: unknown | undefined);
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* Input helpers for reading and parsing stdin in bin command scripts.
|
|
685
|
+
*
|
|
686
|
+
* @example
|
|
687
|
+
* ```typescript
|
|
688
|
+
* import { z } from "zod";
|
|
689
|
+
* import { input } from "@hmcs/sdk/commands";
|
|
690
|
+
*
|
|
691
|
+
* const data = await input.parse(
|
|
692
|
+
* z.object({ name: z.string(), count: z.number() })
|
|
693
|
+
* );
|
|
694
|
+
* ```
|
|
695
|
+
*/
|
|
696
|
+
declare namespace input {
|
|
697
|
+
/**
|
|
698
|
+
* Read all of stdin as a UTF-8 string.
|
|
699
|
+
*
|
|
700
|
+
* Consumes the entire `process.stdin` stream via async iteration and returns
|
|
701
|
+
* the concatenated result. Useful when you need the raw string without JSON
|
|
702
|
+
* parsing or validation.
|
|
703
|
+
*
|
|
704
|
+
* @example
|
|
705
|
+
* ```typescript
|
|
706
|
+
* import { input } from "@hmcs/sdk/commands";
|
|
707
|
+
*
|
|
708
|
+
* const raw = await input.read();
|
|
709
|
+
* console.log("Received:", raw);
|
|
710
|
+
* ```
|
|
711
|
+
*/
|
|
712
|
+
function read(): Promise<string>;
|
|
713
|
+
/**
|
|
714
|
+
* Read JSON from stdin and validate it against a Zod schema.
|
|
715
|
+
*
|
|
716
|
+
* Performs three steps:
|
|
717
|
+
* 1. Reads all of stdin via {@link input.read}
|
|
718
|
+
* 2. Parses the raw string as JSON
|
|
719
|
+
* 3. Validates the parsed object against the provided Zod schema
|
|
720
|
+
*
|
|
721
|
+
* @typeParam T - The output type inferred from the Zod schema
|
|
722
|
+
* @param schema - A Zod schema to validate the parsed JSON against
|
|
723
|
+
* @returns The validated and typed input object
|
|
724
|
+
* @throws {StdinParseError} With `code: "EMPTY_STDIN"` if stdin is empty or whitespace-only
|
|
725
|
+
* @throws {StdinParseError} With `code: "INVALID_JSON"` if stdin is not valid JSON
|
|
726
|
+
* @throws {StdinParseError} With `code: "VALIDATION_ERROR"` if the JSON does not match the schema
|
|
727
|
+
*
|
|
728
|
+
* @example
|
|
729
|
+
* ```typescript
|
|
730
|
+
* import { z } from "zod";
|
|
731
|
+
* import { input } from "@hmcs/sdk/commands";
|
|
732
|
+
*
|
|
733
|
+
* const data = await input.parse(
|
|
734
|
+
* z.object({
|
|
735
|
+
* entity: z.number(),
|
|
736
|
+
* text: z.union([z.string(), z.array(z.string())]),
|
|
737
|
+
* speaker: z.number().default(0),
|
|
738
|
+
* })
|
|
739
|
+
* );
|
|
740
|
+
* ```
|
|
741
|
+
*/
|
|
742
|
+
function parse<T>(schema: ZodType<T>): Promise<T>;
|
|
743
|
+
/**
|
|
744
|
+
* Parse menu command stdin and return the linked VRM instance.
|
|
745
|
+
*
|
|
746
|
+
* Menu commands receive `{ "linkedVrm": <entityId> }` on stdin from the
|
|
747
|
+
* menu UI. This helper validates the input and returns a ready-to-use
|
|
748
|
+
* {@link Vrm} instance.
|
|
749
|
+
*
|
|
750
|
+
* @returns A {@link Vrm} instance for the linked entity
|
|
751
|
+
* @throws {StdinParseError} With `code: "EMPTY_STDIN"` if stdin is empty
|
|
752
|
+
* @throws {StdinParseError} With `code: "INVALID_JSON"` if stdin is not valid JSON
|
|
753
|
+
* @throws {StdinParseError} With `code: "VALIDATION_ERROR"` if `linkedVrm` is missing or not a number
|
|
754
|
+
*
|
|
755
|
+
* @example
|
|
756
|
+
* ```typescript
|
|
757
|
+
* import { input } from "@hmcs/sdk/commands";
|
|
758
|
+
*
|
|
759
|
+
* const vrm = await input.parseMenu();
|
|
760
|
+
* await vrm.setExpressions({ happy: 1.0 });
|
|
761
|
+
* ```
|
|
762
|
+
*/
|
|
763
|
+
function parseMenu(): Promise<Vrm>;
|
|
764
|
+
}
|
|
765
|
+
/**
|
|
766
|
+
* Output helpers for writing structured results and errors in bin command scripts.
|
|
767
|
+
*
|
|
768
|
+
* @example
|
|
769
|
+
* ```typescript
|
|
770
|
+
* import { output } from "@hmcs/sdk/commands";
|
|
771
|
+
*
|
|
772
|
+
* output.succeed({ count: 42, status: "done" });
|
|
773
|
+
* ```
|
|
774
|
+
*/
|
|
775
|
+
declare namespace output {
|
|
776
|
+
/**
|
|
777
|
+
* Write a JSON-serialized result to stdout (fd 1).
|
|
778
|
+
*
|
|
779
|
+
* Serializes `data` with `JSON.stringify` and writes it followed by a newline
|
|
780
|
+
* to file descriptor 1 using synchronous I/O. This ensures the output is
|
|
781
|
+
* flushed before the process exits.
|
|
782
|
+
*
|
|
783
|
+
* @param data - The value to serialize as JSON and write to stdout
|
|
784
|
+
*
|
|
785
|
+
* @example
|
|
786
|
+
* ```typescript
|
|
787
|
+
* import { output } from "@hmcs/sdk/commands";
|
|
788
|
+
*
|
|
789
|
+
* output.write({ count: 42, status: "done" });
|
|
790
|
+
* // stdout receives: {"count":42,"status":"done"}\n
|
|
791
|
+
* ```
|
|
792
|
+
*/
|
|
793
|
+
function write(data: unknown): void;
|
|
794
|
+
/**
|
|
795
|
+
* Write a structured JSON error to stderr (fd 2).
|
|
796
|
+
*
|
|
797
|
+
* Serializes an object with `code` and `message` fields and writes it followed
|
|
798
|
+
* by a newline to file descriptor 2 using synchronous I/O.
|
|
799
|
+
*
|
|
800
|
+
* @param code - A machine-readable error code (e.g., `"NOT_FOUND"`, `"TIMEOUT"`)
|
|
801
|
+
* @param message - A human-readable error description
|
|
802
|
+
*
|
|
803
|
+
* @example
|
|
804
|
+
* ```typescript
|
|
805
|
+
* import { output } from "@hmcs/sdk/commands";
|
|
806
|
+
*
|
|
807
|
+
* output.writeError("NOT_FOUND", "Entity 42 does not exist");
|
|
808
|
+
* // stderr receives: {"code":"NOT_FOUND","message":"Entity 42 does not exist"}\n
|
|
809
|
+
* ```
|
|
810
|
+
*/
|
|
811
|
+
function writeError(code: string, message: string): void;
|
|
812
|
+
/**
|
|
813
|
+
* Write a JSON result to stdout and exit the process with code 0.
|
|
814
|
+
*
|
|
815
|
+
* This is a convenience wrapper that calls {@link output.write} followed by
|
|
816
|
+
* `process.exit(0)`. Use this as the final call in a successful bin command.
|
|
817
|
+
*
|
|
818
|
+
* @param data - The value to serialize as JSON and write to stdout
|
|
819
|
+
*
|
|
820
|
+
* @example
|
|
821
|
+
* ```typescript
|
|
822
|
+
* import { input, output } from "@hmcs/sdk/commands";
|
|
823
|
+
*
|
|
824
|
+
* const data = await input.parse(schema);
|
|
825
|
+
* const result = await doWork(data);
|
|
826
|
+
* output.succeed({ processed: result.count });
|
|
827
|
+
* ```
|
|
828
|
+
*/
|
|
829
|
+
function succeed(data: unknown): never;
|
|
830
|
+
/**
|
|
831
|
+
* Write a structured error to stderr and exit the process.
|
|
832
|
+
*
|
|
833
|
+
* This is a convenience wrapper that calls {@link output.writeError} followed by
|
|
834
|
+
* `process.exit(exitCode)`. Use this when a bin command encounters a fatal error.
|
|
835
|
+
*
|
|
836
|
+
* @param code - A machine-readable error code (e.g., `"NOT_FOUND"`, `"TIMEOUT"`)
|
|
837
|
+
* @param message - A human-readable error description
|
|
838
|
+
* @param exitCode - Process exit code (default: `1`)
|
|
839
|
+
*
|
|
840
|
+
* @example
|
|
841
|
+
* ```typescript
|
|
842
|
+
* import { output } from "@hmcs/sdk/commands";
|
|
843
|
+
*
|
|
844
|
+
* if (!response.ok) {
|
|
845
|
+
* output.fail("API_ERROR", `Server returned ${response.status}`);
|
|
846
|
+
* }
|
|
847
|
+
* ```
|
|
848
|
+
*/
|
|
849
|
+
function fail(code: string, message: string, exitCode?: number): never;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
export { StdinParseError, input, output };
|