@viji-dev/core 0.8.17 → 0.10.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/dist/index.d.ts CHANGED
@@ -307,7 +307,9 @@ export declare class AudioSystem {
307
307
  private debugLog;
308
308
  private fftSize;
309
309
  private audioStateBeat;
310
- private sendAnalysisResults;
310
+ private analysisSinks;
311
+ private latestChannelResults;
312
+ private channelMeta;
311
313
  constructor(sendAnalysisResultsCallback?: (data: any) => void);
312
314
  /**
313
315
  * Get the current audio analysis state (for host-side usage)
@@ -420,6 +422,33 @@ export declare class AudioSystem {
420
422
  * Tags with streamIndex and conditionally includes beat data (main channel only).
421
423
  */
422
424
  private sendChannelResults;
425
+ /**
426
+ * Deliver an analysis message to one sink with PER-SINK typed-array
427
+ * copies. The host→worker relay transfers `frequencyData`/`waveformData`
428
+ * buffers (zero-copy receive, `collectTransferables` case
429
+ * 'audio-analysis-update') — posting the same message object to N sinks
430
+ * would let the first post DETACH the buffers and starve every other
431
+ * sink (and the replay cache). One copy per sink per analysis frame is
432
+ * the unavoidable cost of a transfer-per-receiver delivery.
433
+ */
434
+ private deliverAnalysisMessage;
435
+ /**
436
+ * Register a result-delivery sink (one per attached core's worker) and
437
+ * replay current state to it in FIFO order: the latest main-channel
438
+ * analysis, then per non-main channel its `audio-stream-setup` identity
439
+ * followed by the latest cached analysis. A mid-stream attach is thereby
440
+ * indistinguishable from a fresh connect on the receiving worker.
441
+ */
442
+ addSink(id: string, send: (message: {
443
+ type: string;
444
+ data: any;
445
+ }) => void): void;
446
+ /**
447
+ * Remove a previously registered result-delivery sink.
448
+ */
449
+ removeSink(id: string): void;
450
+ private buildStreamSetupMessage;
451
+ private emitStreamSetup;
423
452
  /**
424
453
  * Reset audio values to defaults (main channel + beat state)
425
454
  */
@@ -436,17 +465,25 @@ export declare class AudioSystem {
436
465
  resetAudioState(): Promise<void>;
437
466
  /**
438
467
  * Add an additional audio stream (lightweight analysis, no beat detection).
439
- * @param streamIndex Global stream index (from VijiCore: AUDIO_ADDITIONAL_BASE + n or AUDIO_DEVICE_BASE + n)
468
+ * When `meta` is provided, the stream identity is recorded and an
469
+ * `audio-stream-setup` message is emitted to every sink (and replayed to
470
+ * sinks attached later).
471
+ * @param streamIndex Global stream index (AUDIO_ADDITIONAL_BASE + n or AUDIO_DEVICE_BASE + n)
440
472
  * @param stream The MediaStream to analyze
473
+ * @param meta Stream identity for the worker-side two-phase setup protocol
441
474
  */
442
- addStream(streamIndex: number, stream: MediaStream): Promise<void>;
475
+ addStream(streamIndex: number, stream: MediaStream, meta?: {
476
+ streamType: 'additional' | 'device';
477
+ deviceId?: string;
478
+ }): Promise<void>;
443
479
  /**
444
480
  * Remove an additional audio stream.
445
481
  */
446
482
  removeStream(streamIndex: number): void;
447
483
  /**
448
- * Tear down all additional channels and rebuild with corrected indices.
449
- * Mirrors video's reinitializeAdditionalCoordinators pattern.
484
+ * Tear down all additional channels in the base range and rebuild with
485
+ * corrected indices, re-emitting `audio-stream-setup` for the re-indexed
486
+ * streams. Mirrors video's reinitializeAdditionalCoordinators pattern.
450
487
  */
451
488
  reinitializeAdditionalChannels(streams: MediaStream[], baseIndex: number): Promise<void>;
452
489
  /**
@@ -2665,7 +2702,7 @@ declare type TrackingState = 'TRACKING' | 'LOCKED' | 'BREAKDOWN' | 'LOST';
2665
2702
  /** Returned by `on*` listener registration calls; invoke to unsubscribe. */
2666
2703
  export declare type Unsubscribe = () => void;
2667
2704
 
2668
- export declare const VERSION = "0.8.17";
2705
+ export declare const VERSION = "0.10.0";
2669
2706
 
2670
2707
  /**
2671
2708
  * Real-time video API: drawable frame, dimensions, and the source-side
@@ -2714,11 +2751,12 @@ export declare interface VideoAPI {
2714
2751
  * outputs (the analysed frame and its detection / segmentation results) with
2715
2752
  * the verbs that activate the underlying MediaPipe pipelines.
2716
2753
  *
2717
- * Available only on the main video stream (`viji.video.cv`). Additional
2718
- * streams (`viji.videoStreams[i].cv`) and device videos
2719
- * (`viji.devices[i].video.cv`) do not run CV; their `cv` surface exists for
2720
- * API consistency but the data fields stay at their empty defaults and the
2721
- * `enable*` verbs are no-ops.
2754
+ * Available on the main video stream (`viji.video.cv`) and on additional
2755
+ * streams (`viji.videoStreams[i].cv`) — same surface, same verbs, activated
2756
+ * per stream. `analysedFrame` is populated on the MAIN stream only; on other
2757
+ * streams it stays `null` (use `currentFrame`). Device videos
2758
+ * (`viji.devices[i].video.cv`) do not run CV yet; their `cv` surface exists
2759
+ * for API consistency with the data fields at their empty defaults.
2722
2760
  */
2723
2761
  export declare interface VideoCVAPI {
2724
2762
  /**
@@ -3024,7 +3062,6 @@ export declare class VijiCore {
3024
3062
  private workerManager;
3025
3063
  private interactionManager;
3026
3064
  private deviceSensorManager;
3027
- private audioSystem;
3028
3065
  private isInitialized;
3029
3066
  private isDestroyed;
3030
3067
  private isInitializing;
@@ -3038,23 +3075,10 @@ export declare class VijiCore {
3038
3075
  private debugLog;
3039
3076
  private config;
3040
3077
  private isHeadless;
3041
- private currentAudioStream;
3042
- private static readonly ADDITIONAL_STREAM_BASE;
3043
- private static readonly DEVICE_VIDEO_BASE;
3044
3078
  private static readonly DIRECT_FRAME_BASE;
3045
- private static readonly AUDIO_ADDITIONAL_BASE;
3046
- private static readonly AUDIO_DEVICE_BASE;
3047
- private static readonly MAX_ADDITIONAL_AUDIO_STREAMS;
3048
- private static readonly MAX_ADDITIONAL_VIDEO_STREAMS;
3049
- private videoStream;
3050
- private videoStreams;
3051
- private audioStreams;
3052
- private deviceAudioStreamIndices;
3053
- private mainVideoCoordinator;
3054
- private additionalCoordinators;
3079
+ private engineGroup;
3080
+ private groupMember;
3055
3081
  private directFrameSlots;
3056
- private deviceVideoCoordinators;
3057
- private deviceVideoStreamIndices;
3058
3082
  private latestFrameBuffer;
3059
3083
  private autoCaptureEnabled;
3060
3084
  private eventSourceCore;
@@ -3066,6 +3090,7 @@ export declare class VijiCore {
3066
3090
  private sceneRenderer;
3067
3091
  private sceneCapabilities;
3068
3092
  private sceneP5CanvasMode?;
3093
+ private sceneConsumesAnalysedFrame;
3069
3094
  private sceneContextType?;
3070
3095
  private parametersInitialized;
3071
3096
  private parameterListeners;
@@ -3367,27 +3392,33 @@ export declare class VijiCore {
3367
3392
  code: string;
3368
3393
  }) => void): void;
3369
3394
  /**
3370
- * Snapshot the full audio analysis + onset state for cross-instance
3371
- * transfer. Use for **same-process scene-switch** continuity (a fresh
3372
- * `VijiCore` can resume detection where the previous one left off).
3395
+ * Snapshot the full audio analysis + onset state for **cross-device**
3396
+ * transfer (e.g. host → second host, multi-machine sync). Pair with
3397
+ * `importFullState` on the receiver, applying an NTP-derived `clockOffset`.
3398
+ *
3399
+ * NOT needed for same-process transitions: construct the successor core
3400
+ * with `{ mediaSource: oldCore }` instead — the shared audio engine (and
3401
+ * its live BPM lock / onset patterns) survives the swap with no
3402
+ * export/import step and no warm-up gap.
3373
3403
  *
3374
- * For **cross-device** transfer, prefer `audio.onset.exportSessionState`
3404
+ * For controller → host onset sync, prefer `audio.onset.exportSessionState`
3375
3405
  * — the controller's audio analysis state doesn't apply to the host's
3376
3406
  * audio source and would corrupt detection.
3377
3407
  *
3378
3408
  * Wall-clock fields are in this instance's `performance.now()` clock space.
3379
- * Receiver applies `clockOffset` on import (use `0` for same-process).
3380
3409
  *
3381
- * **Staleness caveat**: the audio block is robust to scene-load gaps under
3382
- * ~1 second. Longer gaps (>5s, e.g. cold cache + slow network) may cause
3410
+ * **Staleness caveat**: the audio block is robust to transfer gaps under
3411
+ * ~1 second. Longer gaps (>5s, e.g. slow network) may cause
3383
3412
  * stale-timestamp drift in `gridLockMemoryTime` / `warmupStartTimeMs`;
3384
3413
  * callers should treat that as a degraded path and skip the audio block.
3385
3414
  */
3386
3415
  exportFullState(): SerializedCoreState;
3387
3416
  /**
3388
- * Replace the audio analysis + onset state from a serialized payload.
3389
- * `clockOffset` is added to all sender-clocked fields (`0` for same-process,
3390
- * NTP-derived for cross-device). Mutation is synchronous.
3417
+ * Replace the audio analysis + onset state from a serialized payload
3418
+ * (**cross-device** transfer — for same-process transitions use
3419
+ * `mediaSource` instead, see {@link exportFullState}).
3420
+ * `clockOffset` is added to all sender-clocked fields (NTP-derived;
3421
+ * `0` only when clocks are genuinely shared). Mutation is synchronous.
3391
3422
  *
3392
3423
  * Field-level events (`onModeChange`, `onMuteChange`) fire when imported
3393
3424
  * values differ from current — consumer-visible state stays consistent
@@ -3482,8 +3513,14 @@ export declare class VijiCore {
3482
3513
  */
3483
3514
  setFrameRate(mode: FrameRateMode): Promise<void>;
3484
3515
  /**
3485
- * Sets the CV processing frame rate mode (relative to scene frame rate)
3486
- * @param mode - CV processing rate: 'full', 'half', 'quarter', or 'eighth' of scene rate
3516
+ * Sets the CV processing frame rate mode, relative to the **video stream
3517
+ * delivery rate** (the capture's ~30 fps), not the scene render rate —
3518
+ * with shared engines, attached scenes may render at different rates, so
3519
+ * the capture rate is the only coherent base.
3520
+ *
3521
+ * Engine-level write: visible to ALL cores sharing this core's media
3522
+ * engines (same rule as the stream mutators).
3523
+ * @param mode - CV processing rate: 'full', 'half', 'quarter', or 'eighth' of the capture rate
3487
3524
  */
3488
3525
  setCVFrameRate(mode: CVFrameRateMode): Promise<void>;
3489
3526
  /**
@@ -3495,57 +3532,76 @@ export declare class VijiCore {
3495
3532
  */
3496
3533
  setAudioStream(audioStream: MediaStream | null): Promise<void>;
3497
3534
  /**
3498
- * Sets the main video stream (CV enabled)
3535
+ * Sets the main video stream (CV enabled).
3536
+ *
3537
+ * Engine-level write: visible to ALL cores sharing this core's media
3538
+ * engines — each attached core's worker gets its own fresh capture for the
3539
+ * new stream. Capability change notifications fan out to all of them.
3499
3540
  */
3500
3541
  setVideoStream(stream: MediaStream | null): Promise<void>;
3501
3542
  /**
3502
- * Gets the main video stream
3543
+ * Gets the main video stream (engine-scoped — identical for all cores
3544
+ * sharing this core's media engines)
3503
3545
  */
3504
3546
  getVideoStream(): MediaStream | null;
3505
3547
  /**
3506
3548
  * Adds an additional video stream (no CV). Returns its index in viji.videoStreams[].
3549
+ *
3550
+ * Engine-level write: the stream appears in `viji.videoStreams[]` of EVERY
3551
+ * core sharing this core's media engines.
3507
3552
  */
3508
3553
  addVideoStream(stream: MediaStream): Promise<number>;
3509
3554
  /**
3510
- * Removes an additional video stream by index.
3555
+ * Removes an additional video stream by index. Stops the stream's tracks.
3556
+ *
3557
+ * Engine-level write: removal (and the resulting re-indexing) is visible to
3558
+ * ALL cores sharing this core's media engines.
3511
3559
  */
3512
3560
  removeVideoStream(index: number): Promise<void>;
3513
3561
  /**
3514
- * Gets the number of additional video streams.
3562
+ * Gets the number of additional video streams (engine-scoped).
3515
3563
  */
3516
3564
  getVideoStreamCount(): number;
3517
3565
  /**
3518
3566
  * Add an additional audio stream for lightweight analysis (no beat detection).
3567
+ *
3568
+ * Engine-level write: the stream appears in `viji.audioStreams[]` of EVERY
3569
+ * core sharing this core's media engines.
3519
3570
  * @param stream MediaStream with audio tracks
3520
3571
  * @returns Index of the new stream (0-based within additional streams)
3521
3572
  * @throws VijiCoreError if limit reached (max 8)
3522
3573
  */
3523
3574
  addAudioStream(stream: MediaStream): Promise<number>;
3524
3575
  /**
3525
- * Remove an additional audio stream by index.
3526
- * Triggers re-indexing of remaining streams.
3576
+ * Remove an additional audio stream by index. Stops the stream's tracks
3577
+ * and triggers re-indexing of remaining streams.
3578
+ *
3579
+ * Engine-level write: removal is visible to ALL cores sharing this core's
3580
+ * media engines.
3527
3581
  */
3528
3582
  removeAudioStream(index: number): Promise<void>;
3529
3583
  /**
3530
- * Gets the number of additional audio streams.
3584
+ * Gets the number of additional audio streams (engine-scoped).
3531
3585
  */
3532
3586
  getAudioStreamCount(): number;
3533
3587
  /**
3534
3588
  * Set audio stream from an external device.
3589
+ *
3590
+ * Engine-level write: visible to ALL cores sharing this core's media
3591
+ * engines. Device registration (`addExternalDevice`) stays per-core.
3535
3592
  * @param deviceId Device identifier (must be registered via addExternalDevice)
3536
3593
  * @param stream MediaStream with audio tracks from the device
3537
3594
  */
3538
3595
  setDeviceAudio(deviceId: string, stream: MediaStream): Promise<void>;
3539
3596
  /**
3540
3597
  * Clear audio stream from a device.
3598
+ *
3599
+ * Engine-level write: visible to ALL cores sharing this core's media engines.
3541
3600
  */
3542
3601
  clearDeviceAudio(deviceId: string): Promise<void>;
3543
3602
  /**
3544
- * Reinitializes all additional coordinators after array mutation.
3545
- */
3546
- private reinitializeAdditionalCoordinators;
3547
- /**
3548
- * Gets the current audio stream
3603
+ * Gets the current audio stream (engine-scoped — identical for all cores
3604
+ * sharing this core's media engines)
3549
3605
  */
3550
3606
  getAudioStream(): MediaStream | null;
3551
3607
  /**
@@ -3556,6 +3612,61 @@ export declare class VijiCore {
3556
3612
  * Gets the current interaction enabled state
3557
3613
  */
3558
3614
  getInteractionEnabled(): boolean;
3615
+ /**
3616
+ * Lazy audio-engine access. Read-only getters use `audioEngine` (never
3617
+ * materializes — headless previews construct nothing); every other
3618
+ * `core.audio.*` call uses `ensureAudioEngine()` (materialize-on-use:
3619
+ * mutators, subscriptions, imports AND exports — a listener registered or
3620
+ * a tap received before any stream exists must hit a live engine, see the
3621
+ * constructor-started idle ticker in AudioSystem).
3622
+ */
3623
+ private get audioEngine();
3624
+ private ensureAudioEngine;
3625
+ /**
3626
+ * Host-side video control namespace. The `cv` sub-namespace lets host
3627
+ * code (as opposed to scene code) drive CV on the main video stream —
3628
+ * the controller use case: a scene-less headless core analyzing its
3629
+ * local camera and shipping results onward.
3630
+ */
3631
+ readonly video: {
3632
+ cv: {
3633
+ /**
3634
+ * Enable or disable a CV feature on the main video stream from the
3635
+ * host side. The host acts as one more consumer of the shared CV
3636
+ * engine: inference runs the union of all consumers' desired sets,
3637
+ * and host results arrive via {@link onResults} filtered to the
3638
+ * host-enabled features.
3639
+ *
3640
+ * Engine-level write: the underlying inference is visible to ALL
3641
+ * cores sharing this core's media engines (scenes still only receive
3642
+ * features they enabled themselves).
3643
+ *
3644
+ * @param feature - The CV feature to toggle
3645
+ * @param enabled - Whether the feature should run
3646
+ */
3647
+ enable: (feature: CVFeature, enabled: boolean) => void;
3648
+ /**
3649
+ * Subscribe to CV results on the host side, filtered to the features
3650
+ * enabled via {@link enable}. Fires once per completed inference with
3651
+ * the same result shapes the artist API exposes
3652
+ * (`faces`/`hands`/`pose`/`segmentation`).
3653
+ *
3654
+ * Engine-level: one listener registry per shared engine group —
3655
+ * subscribe once per app.
3656
+ *
3657
+ * @returns Unsubscribe function. Call to remove the listener.
3658
+ */
3659
+ onResults: (listener: (update: {
3660
+ streamIndex: number;
3661
+ results: {
3662
+ faces?: FaceData[];
3663
+ hands?: HandData[];
3664
+ pose?: PoseData | null;
3665
+ segmentation?: SegmentationData | null;
3666
+ };
3667
+ }) => void) => Unsubscribe;
3668
+ };
3669
+ };
3559
3670
  readonly audio: {
3560
3671
  /**
3561
3672
  * Beat control namespace
@@ -3637,6 +3748,11 @@ export declare class VijiCore {
3637
3748
  *
3638
3749
  * Idempotent transitions (already in target mode) do not fire.
3639
3750
  *
3751
+ * Engine-level: the listener registry lives on the shared audio engine,
3752
+ * so subscribing through several cores that share media engines targets
3753
+ * ONE registry — subscribe once per app. The same function reference is
3754
+ * deduped by identity; distinct closures doing the same work are not.
3755
+ *
3640
3756
  * @returns Unsubscribe function. Call to remove the listener.
3641
3757
  */
3642
3758
  onModeChange: (listener: (ev: OnsetModeChangeEvent) => void) => Unsubscribe;
@@ -3656,6 +3772,9 @@ export declare class VijiCore {
3656
3772
  * when fields differ; this event does not because session-end is a
3657
3773
  * different category — about session lifecycle, not field state.
3658
3774
  *
3775
+ * Engine-level: one registry per shared audio engine — subscribe once
3776
+ * per app (see {@link onModeChange}).
3777
+ *
3659
3778
  * @returns Unsubscribe function. Call to remove the listener.
3660
3779
  */
3661
3780
  onSessionEnd: (listener: (ev: OnsetSessionEndEvent) => void) => Unsubscribe;
@@ -3671,6 +3790,9 @@ export declare class VijiCore {
3671
3790
  * Idempotent calls (e.g. `setMuted(true)` on an already-muted instrument)
3672
3791
  * do not fire.
3673
3792
  *
3793
+ * Engine-level: one registry per shared audio engine — subscribe once
3794
+ * per app (see {@link onModeChange}).
3795
+ *
3674
3796
  * @returns Unsubscribe function. Call to remove the listener.
3675
3797
  */
3676
3798
  onMuteChange: (listener: (ev: OnsetMuteChangeEvent) => void) => Unsubscribe;
@@ -3717,7 +3839,11 @@ export declare class VijiCore {
3717
3839
  importSessionState: (state: SerializedOnsetState, clockOffset: number) => void;
3718
3840
  };
3719
3841
  /**
3720
- * Advanced audio controls
3842
+ * Advanced audio controls.
3843
+ *
3844
+ * Engine-level: these settings live on the shared audio engine and are
3845
+ * visible to ALL cores sharing this core's media engines (same rule as
3846
+ * the stream mutators).
3721
3847
  */
3722
3848
  advanced: {
3723
3849
  /**
@@ -3848,6 +3974,13 @@ export declare class VijiCore {
3848
3974
  * Gets current performance statistics
3849
3975
  */
3850
3976
  getStats(): PerformanceStats;
3977
+ /**
3978
+ * Merge the shared CV engine's main-stream processing stats into
3979
+ * `stats.cv`. The cv block is absent until CV state exists (no engine, or
3980
+ * no features ever requested on the main stream) — same shape consumers
3981
+ * saw when the worker produced it.
3982
+ */
3983
+ private mergeCVStats;
3851
3984
  /**
3852
3985
  * Pauses the scene render loop — stops the worker from rendering. Intended to
3853
3986
  * be driven from the host on `document.hidden`, so a hidden tab doesn't keep
@@ -3939,12 +4072,20 @@ export declare class VijiCore {
3939
4072
  /**
3940
4073
  * Set video stream for an external device
3941
4074
  * Device camera will appear in viji.devices[].video
4075
+ *
4076
+ * Engine-level write: every core sharing this core's media engines gets
4077
+ * its own capture of the device stream. Device registration
4078
+ * (`addExternalDevice`) and sensor state stay per-core, so each attached
4079
+ * core's host app registers the device on that core — the worker
4080
+ * self-heals whichever of stream/registration arrives last.
3942
4081
  * @param deviceId - Device identifier
3943
4082
  * @param stream - MediaStream from device camera
3944
4083
  */
3945
4084
  setDeviceVideo(deviceId: string, stream: MediaStream): Promise<void>;
3946
4085
  /**
3947
4086
  * Clear video stream from device
4087
+ *
4088
+ * Engine-level write: visible to ALL cores sharing this core's media engines.
3948
4089
  * @param deviceId - Device identifier
3949
4090
  */
3950
4091
  clearDeviceVideo(deviceId: string): Promise<void>;
@@ -4004,8 +4145,27 @@ export declare interface VijiCoreConfig {
4004
4145
  videoStreams?: MediaStream[];
4005
4146
  /** Additional audio input streams (lightweight analysis, no beat detection) */
4006
4147
  audioStreams?: MediaStream[];
4007
- /** Disable input processing (for preview instances) */
4008
- noInputs?: boolean;
4148
+ /**
4149
+ * Share another core's media analysis engines instead of creating private
4150
+ * ones. The new core attaches to the referenced core's engine group at
4151
+ * construction time and detaches on `destroy()`; the engines (audio
4152
+ * analysis, video capture) survive as long as ANY attached core is alive,
4153
+ * so analysis state (BPM lock, onset patterns, stream connections) carries
4154
+ * across core transitions with no export/import step.
4155
+ *
4156
+ * Mutually exclusive with `audioStream`, `videoStream`, `audioStreams`,
4157
+ * and `videoStreams` — the engine group already owns the streams.
4158
+ *
4159
+ * Stream mutators (`setAudioStream`, `setVideoStream`, `addAudioStream`,
4160
+ * `setDeviceAudio`, …) called on ANY attached core write to the shared
4161
+ * engines and are visible to ALL attached cores.
4162
+ *
4163
+ * The referenced core must not be destroyed and must not have a fenced
4164
+ * benchmark in flight (`BENCHMARK_NOT_ALLOWED`). The reference is resolved
4165
+ * to the engine group at construction; it is not retained afterwards and
4166
+ * is omitted from the `configuration` getter.
4167
+ */
4168
+ mediaSource?: VijiCore;
4009
4169
  /** Enable user interaction events (DOM event capture, disabled in headless by default) */
4010
4170
  allowUserInteraction?: boolean;
4011
4171
  /** Enable device sensor APIs (motion, orientation) */
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A as s, C as o, I as E, V as i, a as A, b as C } from "./index-Cvk3ZfuY.js";
1
+ import { A as s, C as o, I as E, V as i, a as A, b as C } from "./index-C-CGSJSn.js";
2
2
  export {
3
3
  s as AudioSystem,
4
4
  o as CV_FEATURE_KEYS,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viji-dev/core",
3
- "version": "0.8.17",
3
+ "version": "0.10.0",
4
4
  "description": "Universal execution engine for Viji Creative scenes",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -49,7 +49,8 @@
49
49
  ],
50
50
  "scripts": {
51
51
  "prebuild": "node scripts/prebuild-clean.mjs && node scripts/sync-version.mjs",
52
- "build": "vite build && node scripts/copy-tasks-assets.mjs && node scripts/build-artist-types.mjs && node scripts/build-docs-api.mjs",
52
+ "version": "npm run build && git add -A",
53
+ "build": "vite build && node scripts/copy-tasks-assets.mjs && node scripts/build-artist-types.mjs && node scripts/lint-artist-types-drift.mjs && node scripts/build-docs-api.mjs",
53
54
  "build:docs": "node scripts/build-docs-api.mjs",
54
55
  "lint:ai-prompts-drift": "node scripts/lint-ai-prompts-drift.mjs",
55
56
  "dev": "node scripts/sync-version.mjs && vite build --watch",