@signalsandsorcery/plugin-sdk 2.34.1 → 2.35.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import React, { ComponentType, ReactNode, DragEvent, Dispatch, SetStateAction } from 'react';
1
+ import React$1, { ReactNode, ComponentType, DragEvent, Dispatch, SetStateAction } from 'react';
2
2
 
3
3
  /**
4
4
  * Plugin SDK Type Definitions
@@ -2324,7 +2324,7 @@ interface TrackDrawerProps {
2324
2324
  /** Optional single-note preview when the user adds a note. */
2325
2325
  onAuditionNote?: (pitch: number, velocity: number, durationMs: number) => void;
2326
2326
  }
2327
- declare function TrackDrawer({ activeTab, onTabChange, trackId, fxState, onFxToggle, onFxPresetChange, onFxDryWetChange, fxDisabled, instruments, currentPluginId, isLoading, onSelect, onRefresh, editorStage, onShowEditor, onBackToInstruments, selectedInstrumentName, soundHistory, soundHistoryCursor, onRestoreSound, onToggleFavorite, onImportSound, importSoundLabel, editNotes, onNotesChange, editBars, editBpm, editSnap, onAuditionNote, }: TrackDrawerProps): React.ReactElement;
2327
+ declare function TrackDrawer({ activeTab, onTabChange, trackId, fxState, onFxToggle, onFxPresetChange, onFxDryWetChange, fxDisabled, instruments, currentPluginId, isLoading, onSelect, onRefresh, editorStage, onShowEditor, onBackToInstruments, selectedInstrumentName, soundHistory, soundHistoryCursor, onRestoreSound, onToggleFavorite, onImportSound, importSoundLabel, editNotes, onNotesChange, editBars, editBpm, editSnap, onAuditionNote, }: TrackDrawerProps): React$1.ReactElement;
2328
2328
 
2329
2329
  /**
2330
2330
  * useTrackLevels — drives the cosmetic per-track strip meters.
@@ -2525,7 +2525,7 @@ interface SDKTrackRowProps {
2525
2525
  * like CrossfadeTrackRow owns a single delete for the whole pair). */
2526
2526
  onDelete?: () => void;
2527
2527
  /** Custom content replacing the prompt input (e.g., sample info display) */
2528
- contentSlot?: React.ReactNode;
2528
+ contentSlot?: React$1.ReactNode;
2529
2529
  /** Toggle mute */
2530
2530
  onMuteToggle: () => void;
2531
2531
  /** Toggle solo */
@@ -2599,7 +2599,7 @@ interface SDKTrackRowProps {
2599
2599
  * a thin peak meter welds to the bottom of the row. Omit to hide it. */
2600
2600
  levels?: TrackLevelsHandle;
2601
2601
  }
2602
- declare function TrackRow({ track, prompt, runtimeState, soloedOut, fxDetailState, drawerOpen, drawerTab, onTabChange, isGenerating, isAuthenticated, error, hasMidi, generationProgress, estimatedGenerationMs, onPromptChange, onGenerate, onShuffle, onCopy, onDelete, contentSlot, onMuteToggle, onSoloToggle, onVolumeChange, onPanChange, onFxToggle, onFxPresetChange, onFxDryWetChange, onToggleFxDrawer, onProgressChange, accentColor, instrumentName, instrumentMissing, onToggleDrawer, availableInstruments, currentInstrumentPluginId, onInstrumentSelect, instrumentsLoading, onRefreshInstruments, editorStage, onShowEditor, onBackToInstruments, soundHistory, soundHistoryCursor, onRestoreSound, onToggleFavorite, onImportSound, importSoundLabel, editNotes, onNotesChange, editBars, editBpm, editSnap, onAuditionNote, drag, levels, }: SDKTrackRowProps): React.ReactElement;
2602
+ declare function TrackRow({ track, prompt, runtimeState, soloedOut, fxDetailState, drawerOpen, drawerTab, onTabChange, isGenerating, isAuthenticated, error, hasMidi, generationProgress, estimatedGenerationMs, onPromptChange, onGenerate, onShuffle, onCopy, onDelete, contentSlot, onMuteToggle, onSoloToggle, onVolumeChange, onPanChange, onFxToggle, onFxPresetChange, onFxDryWetChange, onToggleFxDrawer, onProgressChange, accentColor, instrumentName, instrumentMissing, onToggleDrawer, availableInstruments, currentInstrumentPluginId, onInstrumentSelect, instrumentsLoading, onRefreshInstruments, editorStage, onShowEditor, onBackToInstruments, soundHistory, soundHistoryCursor, onRestoreSound, onToggleFavorite, onImportSound, importSoundLabel, editNotes, onNotesChange, editBars, editBpm, editSnap, onAuditionNote, drag, levels, }: SDKTrackRowProps): React$1.ReactElement;
2603
2603
 
2604
2604
  /**
2605
2605
  * Crossfade-pair metadata — family-agnostic types + parsing shared by every
@@ -2762,7 +2762,7 @@ interface CrossfadeTrackRowProps {
2762
2762
  /** Left-border accent. Defaults to transition purple. */
2763
2763
  accentColor?: string;
2764
2764
  }
2765
- declare function CrossfadeTrackRow({ origin, target, sliderPos, onMuteToggle, onSoloToggle, onVolumeChange, onPanChange, onDelete, onSliderChange, levels, accentColor, }: CrossfadeTrackRowProps): React.ReactElement;
2765
+ declare function CrossfadeTrackRow({ origin, target, sliderPos, onMuteToggle, onSoloToggle, onVolumeChange, onPanChange, onDelete, onSliderChange, levels, accentColor, }: CrossfadeTrackRowProps): React$1.ReactElement;
2766
2766
 
2767
2767
  /**
2768
2768
  * Crossfade MIDI inpainting — builds the LLM user-prompt for a bridge that
@@ -2984,7 +2984,7 @@ interface FadeTrackRowProps {
2984
2984
  /** Left-border accent. Defaults to transition purple. */
2985
2985
  accentColor?: string;
2986
2986
  }
2987
- declare function FadeTrackRow({ layer, direction, gesture, effect, sliderPos, onMuteToggle, onSoloToggle, onVolumeChange, onPanChange, onDelete, onSliderChange, levels, accentColor, }: FadeTrackRowProps): React.ReactElement;
2987
+ declare function FadeTrackRow({ layer, direction, gesture, effect, sliderPos, onMuteToggle, onSoloToggle, onVolumeChange, onPanChange, onDelete, onSliderChange, levels, accentColor, }: FadeTrackRowProps): React$1.ReactElement;
2988
2988
 
2989
2989
  /**
2990
2990
  * FadeModal — "add a fade" picker for a transition scene.
@@ -3039,7 +3039,7 @@ interface FadeModalProps {
3039
3039
  /** data-testid prefix. */
3040
3040
  testIdPrefix?: string;
3041
3041
  }
3042
- declare function FadeModal({ host, open, fromSceneId, toSceneId, fromSceneName, toSceneName, excludeSourceDbIds, onClose, onCreate, testIdPrefix, }: FadeModalProps): React.ReactElement | null;
3042
+ declare function FadeModal({ host, open, fromSceneId, toSceneId, fromSceneName, toSceneName, excludeSourceDbIds, onClose, onCreate, testIdPrefix, }: FadeModalProps): React$1.ReactElement | null;
3043
3043
 
3044
3044
  /**
3045
3045
  * ImportTrackModal — "import a track from another scene" picker (SDK component).
@@ -3097,7 +3097,7 @@ interface ImportTrackModalProps {
3097
3097
  role?: string;
3098
3098
  }) => void | Promise<void>;
3099
3099
  }
3100
- declare function ImportTrackModal({ host, open, onClose, onImported, title, testIdPrefix, mode, onPick, onPortTrack, }: ImportTrackModalProps): React.ReactElement | null;
3100
+ declare function ImportTrackModal({ host, open, onClose, onImported, title, testIdPrefix, mode, onPick, onPortTrack, }: ImportTrackModalProps): React$1.ReactElement | null;
3101
3101
 
3102
3102
  /**
3103
3103
  * CrossfadeModal — "add a crossfade track" picker for a transition scene.
@@ -3153,7 +3153,7 @@ interface CrossfadeModalProps {
3153
3153
  /** data-testid prefix. */
3154
3154
  testIdPrefix?: string;
3155
3155
  }
3156
- declare function CrossfadeModal({ host, open, fromSceneId, toSceneId, fromSceneName, toSceneName, excludeSourceDbIds, onClose, onCreate, testIdPrefix, }: CrossfadeModalProps): React.ReactElement | null;
3156
+ declare function CrossfadeModal({ host, open, fromSceneId, toSceneId, fromSceneName, toSceneName, excludeSourceDbIds, onClose, onCreate, testIdPrefix, }: CrossfadeModalProps): React$1.ReactElement | null;
3157
3157
 
3158
3158
  /**
3159
3159
  * TransitionDesigner — the per-panel transition staging board, rendered INLINE as
@@ -3221,7 +3221,7 @@ interface TransitionDesignerProps {
3221
3221
  /** data-testid prefix. */
3222
3222
  testIdPrefix?: string;
3223
3223
  }
3224
- declare function TransitionDesigner({ host, fromSceneId, toSceneId, transitionSceneId, excludeSourceDbIds, onCreateCrossfade, onCreateFade, onCreateAudioTransition, familyLabel, testIdPrefix, }: TransitionDesignerProps): React.ReactElement;
3224
+ declare function TransitionDesigner({ host, fromSceneId, toSceneId, transitionSceneId, excludeSourceDbIds, onCreateCrossfade, onCreateFade, onCreateAudioTransition, familyLabel, testIdPrefix, }: TransitionDesignerProps): React$1.ReactElement;
3225
3225
 
3226
3226
  /**
3227
3227
  * Transition Designer — pure helpers for the per-panel transition staging board.
@@ -3351,7 +3351,7 @@ interface ConfirmDialogProps {
3351
3351
  /** Bold heading line. */
3352
3352
  title: string;
3353
3353
  /** Body copy — a string or richer node. */
3354
- message: React.ReactNode;
3354
+ message: React$1.ReactNode;
3355
3355
  /** Confirm button label (default "Delete"). */
3356
3356
  confirmLabel?: string;
3357
3357
  /** Cancel button label (default "Cancel"). */
@@ -3365,7 +3365,7 @@ interface ConfirmDialogProps {
3365
3365
  /** data-testid prefix so each dialog is addressable in tests. */
3366
3366
  testIdPrefix?: string;
3367
3367
  }
3368
- declare function ConfirmDialog({ open, title, message, confirmLabel, cancelLabel, destructive, onConfirm, onCancel, testIdPrefix, }: ConfirmDialogProps): React.ReactElement | null;
3368
+ declare function ConfirmDialog({ open, title, message, confirmLabel, cancelLabel, destructive, onConfirm, onCancel, testIdPrefix, }: ConfirmDialogProps): React$1.ReactElement | null;
3369
3369
 
3370
3370
  /**
3371
3371
  * Modal — the SDK's one modal-stacking primitive (portal + z-tier + backdrop).
@@ -3392,7 +3392,7 @@ interface ModalProps {
3392
3392
  /** Close handler — fired on Escape and backdrop click. */
3393
3393
  onClose: () => void;
3394
3394
  /** The dialog box. Give it `onClick={e => e.stopPropagation()}`. */
3395
- children: React.ReactNode;
3395
+ children: React$1.ReactNode;
3396
3396
  /** data-testid prefix; the backdrop is `${testIdPrefix}-overlay`. */
3397
3397
  testIdPrefix?: string;
3398
3398
  /** Close when the backdrop is clicked (default true). */
@@ -3400,9 +3400,9 @@ interface ModalProps {
3400
3400
  /** Close on Escape (default true). */
3401
3401
  closeOnEscape?: boolean;
3402
3402
  /** Focused when the modal opens (e.g. a Cancel button) so a reflexive Enter is safe. */
3403
- initialFocusRef?: React.RefObject<HTMLElement>;
3403
+ initialFocusRef?: React$1.RefObject<HTMLElement>;
3404
3404
  }
3405
- declare function Modal({ open, onClose, children, testIdPrefix, closeOnBackdrop, closeOnEscape, initialFocusRef, }: ModalProps): React.ReactElement | null;
3405
+ declare function Modal({ open, onClose, children, testIdPrefix, closeOnBackdrop, closeOnEscape, initialFocusRef, }: ModalProps): React$1.ReactElement | null;
3406
3406
 
3407
3407
  /**
3408
3408
  * PianoRollEditor — a compact, DOM-based MIDI note editor for the track drawer.
@@ -3507,7 +3507,7 @@ interface PianoRollEditorProps {
3507
3507
  /** Test id for the outer container. Default "sdk-piano-roll". */
3508
3508
  testId?: string;
3509
3509
  }
3510
- declare function PianoRollEditor({ notes, onChange, bars, bpm, beatsPerBar, snap, snapOptions, onSnapChange, minPitch, maxPitch, autoFit, onAuditionNote, defaultVelocity, disabled, className, testId, }: PianoRollEditorProps): React.ReactElement;
3510
+ declare function PianoRollEditor({ notes, onChange, bars, bpm, beatsPerBar, snap, snapOptions, onSnapChange, minPitch, maxPitch, autoFit, onAuditionNote, defaultVelocity, disabled, className, testId, }: PianoRollEditorProps): React$1.ReactElement;
3511
3511
 
3512
3512
  /**
3513
3513
  * VolumeSlider Component
@@ -3526,7 +3526,7 @@ interface VolumeSliderProps {
3526
3526
  /** Additional CSS classes */
3527
3527
  className?: string;
3528
3528
  }
3529
- declare const VolumeSlider: React.FC<VolumeSliderProps>;
3529
+ declare const VolumeSlider: React$1.FC<VolumeSliderProps>;
3530
3530
 
3531
3531
  /**
3532
3532
  * PanSlider Component
@@ -3546,7 +3546,7 @@ interface PanSliderProps {
3546
3546
  /** Additional CSS classes */
3547
3547
  className?: string;
3548
3548
  }
3549
- declare const PanSlider: React.FC<PanSliderProps>;
3549
+ declare const PanSlider: React$1.FC<PanSliderProps>;
3550
3550
 
3551
3551
  /**
3552
3552
  * FxToggleBar Component
@@ -3565,7 +3565,7 @@ interface FxToggleBarProps {
3565
3565
  onDryWetChange: (trackId: string, category: FxCategory, value: number) => void;
3566
3566
  disabled?: boolean;
3567
3567
  }
3568
- declare const FxToggleBar: React.FC<FxToggleBarProps>;
3568
+ declare const FxToggleBar: React$1.FC<FxToggleBarProps>;
3569
3569
 
3570
3570
  /**
3571
3571
  * SorceryProgressBar Component
@@ -3620,7 +3620,7 @@ declare function calculateTimeBasedTarget(elapsedMs: number, estimatedDurationMs
3620
3620
  /**
3621
3621
  * SorceryProgressBar - A mystical progress bar for uncertain wait times
3622
3622
  */
3623
- declare function SorceryProgressBar({ isLoading, statusText, completeText, onComplete, heightClass, initialProgress, onProgressChange, estimatedDurationMs, }: SorceryProgressBarProps): React.ReactElement | null;
3623
+ declare function SorceryProgressBar({ isLoading, statusText, completeText, onComplete, heightClass, initialProgress, onProgressChange, estimatedDurationMs, }: SorceryProgressBarProps): React$1.ReactElement | null;
3624
3624
 
3625
3625
  /**
3626
3626
  * DownloadPackButton — versioned-pack download trigger (SDK component).
@@ -3647,7 +3647,7 @@ interface DownloadPackButtonProps {
3647
3647
  /** Called once after the install completes (status === 'complete'). */
3648
3648
  onDownloadComplete?: () => void;
3649
3649
  }
3650
- declare const DownloadPackButton: React.FC<DownloadPackButtonProps>;
3650
+ declare const DownloadPackButton: React$1.FC<DownloadPackButtonProps>;
3651
3651
 
3652
3652
  /**
3653
3653
  * SamplePackCTACard — empty-state card a generator panel renders when its
@@ -3674,7 +3674,7 @@ interface SamplePackCTACardProps {
3674
3674
  status: SamplePackCTACardStatus;
3675
3675
  onDownloadComplete?: () => void;
3676
3676
  }
3677
- declare const SamplePackCTACard: React.FC<SamplePackCTACardProps>;
3677
+ declare const SamplePackCTACard: React$1.FC<SamplePackCTACardProps>;
3678
3678
 
3679
3679
  /**
3680
3680
  * WaveformView — small canvas waveform for an audio file on disk.
@@ -3707,7 +3707,7 @@ interface WaveformViewProps {
3707
3707
  */
3708
3708
  targetSamples?: number;
3709
3709
  }
3710
- declare const WaveformView: React.FC<WaveformViewProps>;
3710
+ declare const WaveformView: React$1.FC<WaveformViewProps>;
3711
3711
 
3712
3712
  /**
3713
3713
  * Shared level-meter component.
@@ -3753,7 +3753,7 @@ interface LevelMeterProps {
3753
3753
  /** Inline test id — make multiple instances distinguishable. */
3754
3754
  'data-testid'?: string;
3755
3755
  }
3756
- declare const LevelMeter: React.FC<LevelMeterProps>;
3756
+ declare const LevelMeter: React$1.FC<LevelMeterProps>;
3757
3757
 
3758
3758
  /**
3759
3759
  * TrackMeterStrip — the thin per-track peak meter welded to the bottom of a
@@ -3776,7 +3776,7 @@ interface TrackMeterStripProps {
3776
3776
  /** Optional className for layout tweaks on the wrapper. */
3777
3777
  className?: string;
3778
3778
  }
3779
- declare const TrackMeterStrip: React.FC<TrackMeterStripProps>;
3779
+ declare const TrackMeterStrip: React$1.FC<TrackMeterStripProps>;
3780
3780
 
3781
3781
  /**
3782
3782
  * ScrollingWaveform — live waveform during recording (Phase 8.10).
@@ -3807,7 +3807,7 @@ interface ScrollingWaveformProps {
3807
3807
  /** Highlight color for the wave. */
3808
3808
  fillStyle?: string;
3809
3809
  }
3810
- declare const ScrollingWaveform: React.FC<ScrollingWaveformProps>;
3810
+ declare const ScrollingWaveform: React$1.FC<ScrollingWaveformProps>;
3811
3811
 
3812
3812
  /**
3813
3813
  * OffsetScrubber — manual sample-offset slider for Lyria-generated audio.
@@ -3847,7 +3847,7 @@ interface OffsetScrubberProps {
3847
3847
  /** Disable interaction (e.g., during generation / split). */
3848
3848
  disabled?: boolean;
3849
3849
  }
3850
- declare function OffsetScrubber({ cuePoints, offsetSamples, projectBpm, meter, onChange, disabled, }: OffsetScrubberProps): React.ReactElement;
3850
+ declare function OffsetScrubber({ cuePoints, offsetSamples, projectBpm, meter, onChange, disabled, }: OffsetScrubberProps): React$1.ReactElement;
3851
3851
 
3852
3852
  /**
3853
3853
  * Shared waveform peaks + canvas drawer.
@@ -3939,51 +3939,6 @@ interface SynthesizeCuePointsOptions {
3939
3939
  }
3940
3940
  declare function synthesizeCuePoints({ bpm, sampleRate, bars, meter, }: SynthesizeCuePointsOptions): PluginCuePoints;
3941
3941
 
3942
- /**
3943
- * useSceneState — Scene-keyed state hook for plugin developers.
3944
- *
3945
- * Works like `useState`, but maintains separate state per scene.
3946
- * When the user switches scenes, the previous scene's state is preserved
3947
- * and restored when they switch back.
3948
- *
3949
- * Returns `[value, setForCurrentScene, setForScene]`:
3950
- * - `value` — state for the currently active scene
3951
- * - `setForCurrentScene(v)` — updates state for whatever scene is active at call time
3952
- * - `setForScene(sceneId, v)` — updates state for a specific scene (for async callbacks)
3953
- *
3954
- * Both setters support the functional updater pattern: `prev => next`.
3955
- *
3956
- * **Important:** For object/array `initialValue`, hoist to a module-level constant
3957
- * to keep the setter callbacks referentially stable:
3958
- * ```ts
3959
- * const EMPTY: string[] = [];
3960
- * const [items, setItems, setItemsForScene] = useSceneState(activeSceneId, EMPTY);
3961
- * ```
3962
- */
3963
- type SetSceneState<T> = (value: T | ((prev: T) => T)) => void;
3964
- type SetSceneStateForScene<T> = (sceneId: string, value: T | ((prev: T) => T)) => void;
3965
- declare function useSceneState<T>(activeSceneId: string | null, initialValue: T): [T, SetSceneState<T>, SetSceneStateForScene<T>];
3966
-
3967
- /**
3968
- * useAnySolo — reactively reports whether ANY track in the project is soloed.
3969
- *
3970
- * Solo is cross-panel: when the user solos a track in ANY panel, the engine's
3971
- * effective-mute model silences every non-soloed track. A panel uses this flag
3972
- * to DIM its own non-soloed rows without lighting their Mute buttons:
3973
- *
3974
- * ```tsx
3975
- * const anySolo = useAnySolo(host);
3976
- * // ...
3977
- * <TrackRow soloedOut={anySolo && !track.runtimeState.solo} ... />
3978
- * ```
3979
- *
3980
- * Refreshes on mount and on every track-state change. `onTrackStateChange`
3981
- * fires for tracks in ALL panels (not just this plugin's), so a solo toggled in
3982
- * another panel updates this flag too.
3983
- */
3984
-
3985
- declare function useAnySolo(host: Pick<PluginHost, 'isAnySoloActive' | 'onTrackStateChange'>): boolean;
3986
-
3987
3942
  /**
3988
3943
  * useSoundHistory — generic, per-track "what sounds has this track had?" stack.
3989
3944
  *
@@ -4045,6 +4000,656 @@ interface UseSoundHistoryResult {
4045
4000
  }
4046
4001
  declare function useSoundHistory(applySound: (trackId: string, descriptor: unknown) => Promise<void>, opts?: UseSoundHistoryOptions): UseSoundHistoryResult;
4047
4002
 
4003
+ /**
4004
+ * Per-track state model shared by every generator panel built on the
4005
+ * panel-core. Verbatim generalization of the synth panel's SynthTrackState
4006
+ * (SynthGeneratorPanel.tsx:67–100) — field names, defaults, and semantics are
4007
+ * frozen by the Phase-0 behavior pin.
4008
+ *
4009
+ * @since SDK 2.35.0
4010
+ */
4011
+
4012
+ /** Internal track state combining handle + runtime state + prompt. */
4013
+ interface GeneratorTrackState {
4014
+ handle: PluginTrackHandle;
4015
+ prompt: string;
4016
+ role: string;
4017
+ runtimeState: PluginTrackRuntimeState;
4018
+ fxDetailState: TrackFxDetailState;
4019
+ drawerOpen: boolean;
4020
+ drawerTab: DrawerTab;
4021
+ editorStage: boolean;
4022
+ isGenerating: boolean;
4023
+ error: string | null;
4024
+ hasMidi: boolean;
4025
+ generationProgress: number;
4026
+ editNotes: PluginMidiNote[];
4027
+ editBars: number;
4028
+ editBpm: number;
4029
+ instrumentPluginId: string | null;
4030
+ instrumentName: string | null;
4031
+ instrumentMissing: boolean;
4032
+ /**
4033
+ * Per-track shuffle history: sound/preset names already handed back since
4034
+ * the track was created OR since the history was reset (which happens
4035
+ * automatically when the pool is exhausted — the family shuffle adapter
4036
+ * reports "exhausted" and the core wipes the history and retries). Cycle
4037
+ * pattern: cycle through everything before any repeat.
4038
+ */
4039
+ shuffleHistory: Set<string>;
4040
+ }
4041
+ /**
4042
+ * Fresh track state with the panel defaults (the add-track literal at
4043
+ * SynthGeneratorPanel.tsx:634–654). `overrides` lets loadTracks hydrate
4044
+ * prompt/role/runtime/fx/etc. from fetched state in one construction.
4045
+ */
4046
+ declare function newTrackState(handle: PluginTrackHandle, overrides?: Partial<Omit<GeneratorTrackState, 'handle'>>): GeneratorTrackState;
4047
+
4048
+ /**
4049
+ * Generic multi-track group seam — the crossfade-pair pattern, family- and
4050
+ * meta-parameterized.
4051
+ *
4052
+ * A "track group" is N normal tracks linked by a shared `groupId` persisted in
4053
+ * scene plugin_data under one key PER MEMBER: `track:<dbId>:<metaKey>`. Groups
4054
+ * are never stored as a group-level record; they are assembled by scanning the
4055
+ * member keys (single source of truth, survives member deletion gracefully).
4056
+ * The panel-core resolves parsed groups against live tracks each render:
4057
+ * complete groups render through a custom group row and their members are
4058
+ * excluded from the normal row list; incomplete groups degrade per the
4059
+ * extension's `isComplete` policy (crossfade: both members required; a bass
4060
+ * voice-group: anchor required).
4061
+ *
4062
+ * This is the seam the crossfade/fade metas established (crossfade-meta.ts);
4063
+ * new group families (e.g. the bass plugin's voice groups) ride it without
4064
+ * panel-core changes.
4065
+ *
4066
+ * @since SDK 2.35.0
4067
+ */
4068
+ /** One parsed member: the scene-data key's dbId + its narrowed meta value. */
4069
+ interface TrackGroupMember<M> {
4070
+ dbId: string;
4071
+ meta: M;
4072
+ }
4073
+ /** One parsed group (members in `sortMembers` order when provided). */
4074
+ interface TrackGroupMeta<M> {
4075
+ groupId: string;
4076
+ members: TrackGroupMember<M>[];
4077
+ }
4078
+ /** How to scan + narrow one group family out of scene plugin_data. */
4079
+ interface GroupParseSpec<M> {
4080
+ /** Scene-data key suffix: scans `track:<dbId>:<metaKey>`. */
4081
+ metaKey: string;
4082
+ /** Defensive narrow (the `asCrossfadeMeta` pattern) — return null to skip. */
4083
+ asMeta(val: unknown): M | null;
4084
+ /** Extract the shared group id from a member meta. */
4085
+ groupIdOf(meta: M): string;
4086
+ /** Stable member order (e.g. by voiceIndex). Omit = scene-data scan order. */
4087
+ sortMembers?(a: TrackGroupMember<M>, b: TrackGroupMember<M>): number;
4088
+ }
4089
+ /**
4090
+ * Scan all `track:<dbId>:<metaKey>` keys in a scene's plugin_data and assemble
4091
+ * groups. Pure — no I/O; caller passes the already-fetched scene data map.
4092
+ */
4093
+ declare function parseTrackGroups<M>(sceneData: Record<string, unknown>, spec: GroupParseSpec<M>): TrackGroupMeta<M>[];
4094
+ /** A group resolved against live tracks (only members whose track exists). */
4095
+ interface ResolvedTrackGroup<M, T> {
4096
+ groupId: string;
4097
+ members: Array<{
4098
+ dbId: string;
4099
+ meta: M;
4100
+ track: T;
4101
+ }>;
4102
+ }
4103
+ interface ResolveGroupsOptions<M, T> {
4104
+ /**
4105
+ * Group completeness policy. A group failing this renders as loose normal
4106
+ * rows instead (its members are NOT excluded). Default: every PARSED member
4107
+ * resolved a live track — the crossfade rule (partner deleted ⇒ degrade).
4108
+ */
4109
+ isComplete?(group: ResolvedTrackGroup<M, T>, parsed: TrackGroupMeta<M>): boolean;
4110
+ }
4111
+ interface ResolvedGroupsResult<M, T> {
4112
+ /** Complete groups, ready for the group row renderer. */
4113
+ resolved: ResolvedTrackGroup<M, T>[];
4114
+ /** dbIds of members of COMPLETE groups — exclude these from normal rows. */
4115
+ memberDbIds: Set<string>;
4116
+ /**
4117
+ * dbIds whose member key exists but whose track is gone (deleted
4118
+ * out-of-band) — candidates for lazy scene-data cleanup.
4119
+ */
4120
+ staleMemberDbIds: string[];
4121
+ }
4122
+ /**
4123
+ * Resolve parsed groups against live track state. Pure; call from a useMemo
4124
+ * keyed on [tracks, parsedGroups] (fresh array identities per call are
4125
+ * expected — do NOT key effects on the arrays without a string-key guard,
4126
+ * see the drift-resync `lastResyncKeyRef` pattern).
4127
+ */
4128
+ declare function resolveTrackGroups<M, T>(parsedGroups: TrackGroupMeta<M>[], tracks: readonly T[], getDbId: (track: T) => string, opts?: ResolveGroupsOptions<M, T>): ResolvedGroupsResult<M, T>;
4129
+
4130
+ /**
4131
+ * Small pure helpers shared by every generator panel — moved verbatim out of
4132
+ * the three panel monoliths (synth/drum/instrument each carried a copy of
4133
+ * pluginFxToToggleFx and an LLM note-response parser).
4134
+ *
4135
+ * @since SDK 2.35.0
4136
+ */
4137
+
4138
+ /**
4139
+ * Build a scene plugin_data key for a track-scoped value. Scene-data keys are
4140
+ * ALWAYS constructed from the stable DB UUID (`handle.dbId`) — never the
4141
+ * engine id, which changes on project reload. This is the ONLY key builder
4142
+ * panels and generation strategies should use.
4143
+ */
4144
+ declare function trackDataKey(dbId: string, suffix: string): string;
4145
+ /** Convert SDK PluginTrackFxDetailState to the FxToggleBar's expected TrackFxDetailState. */
4146
+ declare function pluginFxToToggleFx(sdkState: PluginTrackFxDetailState): TrackFxDetailState;
4147
+ /** Shape of the parsed flat LLM JSON note response. */
4148
+ interface LLMNoteResponse {
4149
+ notes: PluginMidiNote[];
4150
+ role?: string;
4151
+ }
4152
+ /**
4153
+ * Parse the LLM JSON response and extract valid MIDI notes (flat
4154
+ * `{notes:[...], role?}` schema). Handles markdown code fences; silently
4155
+ * filters invalid notes; returns null when nothing parses.
4156
+ */
4157
+ declare function parseLLMNoteResponse(content: string): LLMNoteResponse | null;
4158
+
4159
+ /**
4160
+ * GeneratorPanelAdapter — the family-specific contract a generator panel
4161
+ * supplies to the shared panel-core (useGeneratorPanelCore + GeneratorPanelShell).
4162
+ *
4163
+ * The core owns everything the three historical panel monoliths duplicated:
4164
+ * track load/reconcile, event subscriptions, prompt persistence, mixer/FX ops,
4165
+ * drawer + piano-roll wiring, shuffle cycling, transition crossfade/fade
4166
+ * machinery, and the render skeleton. The adapter supplies what genuinely
4167
+ * differs per family: sound serialization, the 🎲 resolver, the generation
4168
+ * pipeline body, create-track options, prompts/parsers, identity strings,
4169
+ * feature flags, and (optionally) custom multi-track group rendering.
4170
+ *
4171
+ * Adapter instances MUST be referentially stable across renders — build them
4172
+ * in a `useMemo(() => createXAdapter(host), [host])`. An unstable adapter
4173
+ * re-creates the core's loadTracks callback every render (the historical
4174
+ * useSoundHistory render-loop failure mode).
4175
+ *
4176
+ * @since SDK 2.35.0
4177
+ */
4178
+
4179
+ /**
4180
+ * Family identity strings + numeric knobs. All panel test-ids derive from
4181
+ * `familyKey` (`add-<key>-track-button`, `<key>-section`, `<key>-view-toggle`,
4182
+ * `no-scene-placeholder-<key>`, `no-contract-placeholder-<key>`,
4183
+ * `<key>-import`, `<key>-sound-import`, `<key>-transition-designer`) — the
4184
+ * synth panel's historical ids are exactly this derivation with key 'synth'.
4185
+ */
4186
+ interface PanelIdentity {
4187
+ /** Test-id + focus-selector stem, e.g. 'synth'. */
4188
+ familyKey: string;
4189
+ /** Human label for the TransitionDesigner header, e.g. 'Synths'. */
4190
+ familyLabel: string;
4191
+ /** New-track name prefix, e.g. 'synth' → `synth-<ts>`. */
4192
+ trackNamePrefix: string;
4193
+ /** Console log tag, e.g. 'SynthGeneratorPanel'. */
4194
+ logTag: string;
4195
+ /** Normal row accent, e.g. '#A78BFA'. */
4196
+ accentColor: string;
4197
+ /** Crossfade/fade row accent, e.g. '#9333EA'. */
4198
+ transitionAccentColor: string;
4199
+ /** Bulk placeholder left-border accent, e.g. '#3B82F6'. */
4200
+ placeholderAccentColor: string;
4201
+ /** Per-plugin per-scene track budget (host enforces 16 too). */
4202
+ maxTracks: number;
4203
+ /** Progress-bar pacing for one generation. */
4204
+ estimatedGenerationMs: number;
4205
+ /** Header button label; default 'Add Track'. */
4206
+ addTrackLabel?: string;
4207
+ /** Header button label; default 'Import Track'. */
4208
+ importTrackLabel?: string;
4209
+ /** Export dialog default filename; default 'midi-tracks'. */
4210
+ exportDefaultName?: string;
4211
+ /**
4212
+ * Plugin id treated as the family's built-in default instrument in the Pick
4213
+ * tab (select it ⇒ close drawer instead of entering the editor stage).
4214
+ * Default 'Surge XT'.
4215
+ */
4216
+ defaultInstrumentPluginId?: string;
4217
+ }
4218
+ /** Which core surfaces this family mounts. */
4219
+ interface PanelFeatureFlags {
4220
+ /** Pick tab + instrument descriptors + editor stage (synth: true). */
4221
+ instrumentPicker: boolean;
4222
+ /** COMPOSING bar + bulk placeholder hybrid phase (synth: true). */
4223
+ bulkComposePlaceholders: boolean;
4224
+ /** "Export Tracks" ZIP button (synth: true). */
4225
+ exportMidi: boolean;
4226
+ /** Transition scene designer + crossfade/fade rows (synth: true). */
4227
+ transitionDesigner: boolean;
4228
+ /** ImportTrackModal + port-track flow + sound-import drawer action (synth: true). */
4229
+ importTracks: boolean;
4230
+ }
4231
+ /** How this family captures / applies / copies a track's SOUND. */
4232
+ interface PanelSoundAdapter {
4233
+ /**
4234
+ * Re-apply an opaque sound-history descriptor (useSoundHistory's applySound).
4235
+ * Synth: `{state, stateType}` through set(Raw)PluginState's dual path.
4236
+ */
4237
+ applySound(trackId: string, descriptor: unknown): Promise<void>;
4238
+ /**
4239
+ * Snapshot the track's current sound as a history descriptor, or null when
4240
+ * the track has no instrument. The CORE records it into soundHistory.
4241
+ */
4242
+ captureSoundDescriptor(trackId: string): Promise<{
4243
+ descriptor: unknown;
4244
+ } | null>;
4245
+ /**
4246
+ * Apply a host.getTrackSound snapshot to a track AND persist it as the
4247
+ * track's durable identity (persistTrackPresetState or family equivalent —
4248
+ * REQUIRED or the transition drift-resync never converges). Returns the
4249
+ * applied label. Used by crossfade/fade copy + drift-resync.
4250
+ */
4251
+ copySnapshot(trackId: string, snap: TrackSoundSnapshot): Promise<string>;
4252
+ /**
4253
+ * Convert a host.getTrackSound snapshot into this family's sound-history
4254
+ * descriptor (synth: `{state, stateType}`). Used by the drawer's sound
4255
+ * import so the imported sound lands in history with the right shape.
4256
+ */
4257
+ descriptorFromSnapshot(snap: TrackSoundSnapshot): unknown;
4258
+ /** Snapshot kind accepted by the drawer's "Import <noun>" (synth: 'preset'). */
4259
+ acceptedSnapshotKind: 'preset' | 'sample' | 'instrument';
4260
+ /** Sound-history cap (synth: 12 — Surge blobs are large). */
4261
+ historyMax: number;
4262
+ /** Drawer action label, e.g. 'Import Preset'. */
4263
+ importSoundLabel: string;
4264
+ /** Noun for import toasts: 'No <noun> to import' / '<Noun> imported'. */
4265
+ importNoun: string;
4266
+ /** History label for the lazily-seeded pre-shuffle sound, e.g. 'Previous preset'. */
4267
+ previousSoundLabel: string;
4268
+ }
4269
+ /** The 🎲: pick + apply one new sound, honoring the exclusion cycle. */
4270
+ interface PanelShuffleAdapter {
4271
+ /**
4272
+ * Pick + apply a sound not in `excludeNames`. Throw when the pool is
4273
+ * exhausted (`isExhaustedError` must recognize it) — the core wipes the
4274
+ * track's history and retries once with an empty exclusion list.
4275
+ */
4276
+ shuffle(track: GeneratorTrackState, excludeNames: string[]): Promise<{
4277
+ appliedName: string;
4278
+ }>;
4279
+ /** Distinguish "pool exhausted" (expected; cycle resets) from real failures. */
4280
+ isExhaustedError(err: unknown): boolean;
4281
+ }
4282
+ /**
4283
+ * Capabilities the core hands to the generation strategy (and group
4284
+ * renderers). Built fresh per call — do not cache across renders.
4285
+ */
4286
+ interface GenerationServices {
4287
+ host: PluginHost;
4288
+ activeSceneId: string | null;
4289
+ /** Live track list snapshot at call time. */
4290
+ tracks: GeneratorTrackState[];
4291
+ /** Patch one track's state (object merge or functional update). */
4292
+ updateTrack(trackId: string, patch: Partial<GeneratorTrackState> | ((t: GeneratorTrackState) => GeneratorTrackState)): void;
4293
+ /** Escape hatch for multi-track updates (reconcile flows). */
4294
+ setTracks: React.Dispatch<React.SetStateAction<GeneratorTrackState[]>>;
4295
+ reloadTracks(incremental?: boolean): Promise<void>;
4296
+ soundHistory: UseSoundHistoryResult;
4297
+ /** Engine id → stable DB UUID (falls back to the input when unknown). */
4298
+ engineToDbId(trackId: string): string;
4299
+ /** The ONLY scene-data key builder (always dbId-based). */
4300
+ trackDataKey(dbId: string, suffix: string): string;
4301
+ /** Latch a track as piano-roll-loaded (post-generation seeding). */
4302
+ markEditLoaded(trackId: string): void;
4303
+ /** Create a family track (adapter options + `<prefix>-<ts><suffix>` name). */
4304
+ createFamilyTrack(nameSuffix?: string): Promise<PluginTrackHandle>;
4305
+ /** Resolved groups for a registered group extension. */
4306
+ resolvedGroups<M>(metaKey: string): ResolvedTrackGroup<M, GeneratorTrackState>[];
4307
+ }
4308
+ /**
4309
+ * One prompt-driven generation turn. The core owns the wrapper: prompt/auth
4310
+ * gates, `isGenerating: true`, and the catch (error patch + 'Generation
4311
+ * failed' toast). The strategy owns the body — synth: LLM → clip on THIS
4312
+ * track → mute → role persist → shufflePreset → success patch; bass: LLM line
4313
+ * → validate/split → reconcile member tracks → per-voice clips + presets →
4314
+ * metas → reload.
4315
+ */
4316
+ interface PanelGenerationStrategy {
4317
+ generate(track: GeneratorTrackState, services: GenerationServices): Promise<void>;
4318
+ }
4319
+ /** Core per-track handlers, same instances the normal rows use. */
4320
+ interface CoreTrackHandlers {
4321
+ promptChange(trackId: string, prompt: string): void;
4322
+ generate(trackId: string): void;
4323
+ shuffle(trackId: string): void;
4324
+ copy(trackId: string): void;
4325
+ delete(trackId: string): void;
4326
+ muteToggle(trackId: string): void;
4327
+ soloToggle(trackId: string): void;
4328
+ volumeChange(trackId: string, volume: number): void;
4329
+ panChange(trackId: string, pan: number): void;
4330
+ tabChange(trackId: string, tab: DrawerTab): void;
4331
+ toggleDrawer(trackId: string): void;
4332
+ toggleFxDrawer(trackId: string): void;
4333
+ notesChange(trackId: string, notes: PluginMidiNote[]): void;
4334
+ progressChange(trackId: string, pct: number): void;
4335
+ }
4336
+ /** Render-time context handed to a group extension's renderGroup. */
4337
+ interface GroupRenderContext {
4338
+ services: GenerationServices;
4339
+ anySolo: boolean;
4340
+ supportsMeters: boolean;
4341
+ levels?: TrackLevelsHandle;
4342
+ handlers: CoreTrackHandlers;
4343
+ /**
4344
+ * Build the shell's default TrackRow for a member with per-row overrides —
4345
+ * group renderers stack these instead of reimplementing the ~50-prop plumbing.
4346
+ */
4347
+ renderDefaultTrackRow(track: GeneratorTrackState, overrides?: Partial<SDKTrackRowProps>, drag?: TrackRowDragProps): ReactNode;
4348
+ /** Optimistic group mute (crossfade group-control pattern). */
4349
+ setGroupMute(trackIds: string[], muted: boolean): void;
4350
+ /** Optimistic group solo. */
4351
+ setGroupSolo(trackIds: string[], solo: boolean): void;
4352
+ /**
4353
+ * Delete all member tracks + their `track:<dbId>:<suffix>` scene-data keys
4354
+ * (per cleanupKeySuffixes) + prune local state. Best-effort per member.
4355
+ */
4356
+ deleteGroup(members: Array<{
4357
+ engineId: string;
4358
+ dbId: string;
4359
+ }>, cleanupKeySuffixes: string[]): Promise<void>;
4360
+ }
4361
+ /**
4362
+ * A family-registered multi-track group row (the crossfade seam,
4363
+ * parameterized). Members of complete groups render through `renderGroup`
4364
+ * and are excluded from the normal row list; incomplete groups degrade to
4365
+ * normal rows per `isComplete`.
4366
+ */
4367
+ interface PanelGroupExtension<M = unknown> extends GroupParseSpec<M> {
4368
+ /**
4369
+ * Completeness policy (default: every parsed member's track is live).
4370
+ * Bass voice-groups: the anchor member (voiceIndex 0) must be live.
4371
+ */
4372
+ isComplete?(group: ResolvedTrackGroup<M, GeneratorTrackState>, parsed: TrackGroupMeta<M>): boolean;
4373
+ renderGroup(group: ResolvedTrackGroup<M, GeneratorTrackState>, ctx: GroupRenderContext): ReactNode;
4374
+ }
4375
+ interface GeneratorPanelAdapter<M = unknown> {
4376
+ identity: PanelIdentity;
4377
+ features: PanelFeatureFlags;
4378
+ /** Options for host.createTrack (name is core-built). Synth: `{loadSynth:true, synthName:'Surge XT'}`. */
4379
+ createTrackOptions(): Omit<CreateTrackOptions, 'name'>;
4380
+ /**
4381
+ * Port-flow sound step after the MIDI copy (cross-panel Import Track).
4382
+ * Synth: `host.shufflePreset(handle.id)` non-fatal.
4383
+ */
4384
+ applyPortedTrackSound(handle: PluginTrackHandle, role?: string): Promise<void>;
4385
+ /** System prompt for the family's LLM calls (incl. core-owned crossfade/fade generation). */
4386
+ buildSystemPrompt(validRoles: readonly string[]): string;
4387
+ /** Parse the family's LLM note responses (crossfade/fade flows). */
4388
+ parseNotesResponse(content: string): LLMNoteResponse | null;
4389
+ sound: PanelSoundAdapter;
4390
+ shuffle: PanelShuffleAdapter;
4391
+ generation: PanelGenerationStrategy;
4392
+ /** Custom multi-track group rows (bass voice groups). */
4393
+ groupExtensions?: PanelGroupExtension<M>[];
4394
+ /** Patch the default TrackRow props per row (drum's sampleName fallback). */
4395
+ mapTrackRowProps?(track: GeneratorTrackState, props: SDKTrackRowProps): SDKTrackRowProps;
4396
+ }
4397
+ /** Panel-local render extension points around the shell's row list. */
4398
+ interface GeneratorPanelSlots {
4399
+ beforeRows?: ReactNode;
4400
+ afterRows?: ReactNode;
4401
+ /** Extra modals (rendered in the normal phase only). */
4402
+ modals?: ReactNode;
4403
+ }
4404
+
4405
+ /**
4406
+ * Transition-scene machinery for panel-core panels — crossfade pair + fade
4407
+ * creation, group controls, sliders, drift re-sync, and fade curve re-apply.
4408
+ * Moved VERBATIM from the synth panel (SynthGeneratorPanel.tsx 715–987,
4409
+ * 1148–1235, 1787–1847) with the family-specific pieces routed through the
4410
+ * GeneratorPanelAdapter (sound copy/persist, system prompt, note parsing,
4411
+ * track naming). Semantics are frozen by the Phase-0 behavior pin.
4412
+ *
4413
+ * Deliberately NOT rewritten onto the generic group seam (group-meta.ts) —
4414
+ * that seam is additive for new families (bass voice groups); migrating
4415
+ * crossfades onto it is a contained follow-up.
4416
+ *
4417
+ * @since SDK 2.35.0
4418
+ */
4419
+
4420
+ /** A crossfade pair resolved against live track state (both members present). */
4421
+ interface ResolvedCrossfadePair extends CrossfadePairMeta {
4422
+ origin: GeneratorTrackState;
4423
+ target: GeneratorTrackState;
4424
+ }
4425
+ /** A fade (transition orphan) resolved against live track state. */
4426
+ interface ResolvedFade extends FadeEntry {
4427
+ track: GeneratorTrackState;
4428
+ }
4429
+ interface UseTransitionOpsInputs {
4430
+ host: PluginHost;
4431
+ adapter: GeneratorPanelAdapter;
4432
+ activeSceneId: string | null;
4433
+ isConnected: boolean;
4434
+ isAuthenticated: boolean;
4435
+ sceneContext: PluginSceneContext | null | undefined;
4436
+ tracks: GeneratorTrackState[];
4437
+ setTracks: React.Dispatch<React.SetStateAction<GeneratorTrackState[]>>;
4438
+ loadTracks(incremental?: boolean): Promise<void>;
4439
+ setCrossfadePairsMeta: React.Dispatch<React.SetStateAction<CrossfadePairMeta[]>>;
4440
+ setFadesMeta: React.Dispatch<React.SetStateAction<FadeEntry[]>>;
4441
+ resolvedCrossfadePairs: ResolvedCrossfadePair[];
4442
+ resolvedFades: ResolvedFade[];
4443
+ }
4444
+ interface TransitionOps {
4445
+ isCreatingCrossfade: boolean;
4446
+ isCreatingFade: boolean;
4447
+ handleCreateCrossfade(origin: CrossfadeSelection, target: CrossfadeSelection): Promise<void>;
4448
+ handleCreateFade(selection: FadeSelection, direction: FadeDirection, gesture: FadeGesture): Promise<void>;
4449
+ handleCrossfadeMute(pair: ResolvedCrossfadePair): void;
4450
+ handleCrossfadeSolo(pair: ResolvedCrossfadePair): void;
4451
+ handleCrossfadeDelete(pair: ResolvedCrossfadePair): Promise<void>;
4452
+ handleCrossfadeSlider(pair: ResolvedCrossfadePair, pos: number): void;
4453
+ handleFadeDelete(fade: ResolvedFade): Promise<void>;
4454
+ handleFadeSlider(fade: ResolvedFade, pos: number): void;
4455
+ }
4456
+ declare function useTransitionOps({ host, adapter, activeSceneId, isConnected, isAuthenticated, sceneContext, tracks, setTracks, loadTracks, setCrossfadePairsMeta, setFadesMeta, resolvedCrossfadePairs, resolvedFades, }: UseTransitionOpsInputs): TransitionOps;
4457
+
4458
+ /**
4459
+ * useGeneratorPanelCore — the shared state/effects/handlers engine behind
4460
+ * generator panels (synth today; bass next; drum/instrument candidates).
4461
+ *
4462
+ * Verbatim extraction of the synth panel monolith's family-agnostic ~85%
4463
+ * (SynthGeneratorPanel.tsx), parameterized by a GeneratorPanelAdapter. Every
4464
+ * timing (500ms prompt debounce, 500ms agent-mutation coalesce, 300ms notes
4465
+ * save, 350ms add-focus), every scene-data key (`track:<dbId>:…`), every
4466
+ * toast string, and every host-call sequence is frozen by the Phase-0
4467
+ * behavior pin (sas-app/src/__tests__/synth-panel-behavior.test.tsx).
4468
+ *
4469
+ * The returned `core` object is consumed by GeneratorPanelShell (render) and
4470
+ * closed over by family adapters (generation strategies, group renderers).
4471
+ *
4472
+ * @since SDK 2.35.0
4473
+ */
4474
+
4475
+ interface UseGeneratorPanelCoreOptions {
4476
+ /** The panel's PluginUIProps, passed through whole. */
4477
+ ui: PluginUIProps;
4478
+ /** Family adapter — MUST be referentially stable (useMemo on [host]). */
4479
+ adapter: GeneratorPanelAdapter;
4480
+ }
4481
+ /** Everything GeneratorPanelShell + family extensions consume. */
4482
+ interface GeneratorPanelCore {
4483
+ ui: PluginUIProps;
4484
+ adapter: GeneratorPanelAdapter;
4485
+ tracks: GeneratorTrackState[];
4486
+ setTracks: React$1.Dispatch<React$1.SetStateAction<GeneratorTrackState[]>>;
4487
+ isLoadingTracks: boolean;
4488
+ loadTracks(incremental?: boolean): Promise<void>;
4489
+ engineToDbId(trackId: string): string;
4490
+ supportsMeters: boolean;
4491
+ trackLevels: TrackLevelsHandle;
4492
+ anySolo: boolean;
4493
+ reorder: UseTrackReorderResult;
4494
+ soundHistory: ReturnType<typeof useSoundHistory>;
4495
+ isComposing: boolean;
4496
+ placeholders: BulkAddPlaceholderTrack[];
4497
+ isAddingTrack: boolean;
4498
+ isExportingMidi: boolean;
4499
+ designerView: boolean;
4500
+ canCrossfade: boolean;
4501
+ needsContract: boolean;
4502
+ xfFromId: string | null;
4503
+ xfToId: string | null;
4504
+ importOpen: boolean;
4505
+ setImportOpen(open: boolean): void;
4506
+ soundImportTarget: GeneratorTrackState | null;
4507
+ setSoundImportTarget(t: GeneratorTrackState | null): void;
4508
+ handleSoundImportPick(sel: {
4509
+ sourceTrackDbId: string;
4510
+ trackName: string;
4511
+ sceneName: string;
4512
+ }): Promise<void>;
4513
+ handlePortTrack(sel: {
4514
+ sourceTrackDbId: string;
4515
+ trackName: string;
4516
+ role?: string;
4517
+ }): Promise<void>;
4518
+ transition: TransitionOps;
4519
+ crossfadePairsMeta: CrossfadePairMeta[];
4520
+ fadesMeta: FadeEntry[];
4521
+ resolvedCrossfadePairs: ResolvedCrossfadePair[];
4522
+ crossfadeMemberDbIds: Set<string>;
4523
+ resolvedFades: ResolvedFade[];
4524
+ fadeMemberDbIds: Set<string>;
4525
+ resolvedGenericGroups: Record<string, ResolvedGroupsResult<unknown, GeneratorTrackState>>;
4526
+ genericGroupMemberDbIds: Set<string>;
4527
+ availableInstruments: InstrumentDescriptor[];
4528
+ instrumentsLoading: boolean;
4529
+ handlers: CoreTrackHandlers;
4530
+ handleGenerate(trackId: string): Promise<void>;
4531
+ handleShuffle(trackId: string): Promise<void>;
4532
+ handleAddTrack(): Promise<void>;
4533
+ handleDeleteTrack(trackId: string): Promise<void>;
4534
+ handleExportMidi(): Promise<void>;
4535
+ handlePromptChange(trackId: string, prompt: string): void;
4536
+ handleMuteToggle(trackId: string): void;
4537
+ handleSoloToggle(trackId: string): void;
4538
+ handleVolumeChange(trackId: string, volume: number): void;
4539
+ handlePanChange(trackId: string, pan: number): void;
4540
+ handleTabChange(trackId: string, tab: DrawerTab): void;
4541
+ handleToggleDrawer(trackId: string): void;
4542
+ toggleFxDrawer(trackId: string): void;
4543
+ handleNotesChange(trackId: string, notes: PluginMidiNote[]): void;
4544
+ handleProgressChange(trackId: string, pct: number): void;
4545
+ handleCopy(trackId: string): Promise<void>;
4546
+ handleFxToggle(trackId: string, category: FxCategory, enabled: boolean): void;
4547
+ handleFxPresetChange(trackId: string, category: FxCategory, presetIndex: number): void;
4548
+ handleFxDryWetChange(trackId: string, category: FxCategory, value: number): void;
4549
+ handleInstrumentSelect(trackId: string, pluginId: string): Promise<void>;
4550
+ handleShowEditor(trackId: string): Promise<void>;
4551
+ handleBackToInstruments(trackId: string): void;
4552
+ handleRefreshInstruments(): void;
4553
+ onAuditionNote(trackId: string, pitch: number, velocity: number, ms: number): void;
4554
+ makeServices(): GenerationServices;
4555
+ setGroupMute(trackIds: string[], muted: boolean): void;
4556
+ setGroupSolo(trackIds: string[], solo: boolean): void;
4557
+ deleteGroup(members: Array<{
4558
+ engineId: string;
4559
+ dbId: string;
4560
+ }>, cleanupKeySuffixes: string[]): Promise<void>;
4561
+ }
4562
+ declare function useGeneratorPanelCore({ ui, adapter, }: UseGeneratorPanelCoreOptions): GeneratorPanelCore;
4563
+
4564
+ /**
4565
+ * GeneratorPanelShell — the shared render skeleton for panel-core panels.
4566
+ *
4567
+ * Verbatim extraction of the synth panel's render phases
4568
+ * (SynthGeneratorPanel.tsx:1849–2195): no-scene gate → no-contract gate →
4569
+ * COMPOSING → placeholder hybrid → normal (modals, mounted-but-hidden
4570
+ * TransitionDesigner, crossfade/fade rows, generic group rows, normal rows,
4571
+ * export button). The ~50-prop TrackRow plumbing that the monolith duplicated
4572
+ * across the hybrid + normal phases lives here ONCE (`buildRowProps`), pinned
4573
+ * by the Phase-0 props snapshot.
4574
+ *
4575
+ * @since SDK 2.35.0
4576
+ */
4577
+
4578
+ interface GeneratorPanelShellProps {
4579
+ core: GeneratorPanelCore;
4580
+ slots?: GeneratorPanelSlots;
4581
+ }
4582
+ declare function GeneratorPanelShell({ core, slots }: GeneratorPanelShellProps): React$1.ReactElement;
4583
+
4584
+ /**
4585
+ * Surge XT sound adapter — the PanelSoundAdapter shared by every family whose
4586
+ * tracks host Surge XT (or a user-picked third-party VST3) as the instrument:
4587
+ * synth and bass today.
4588
+ *
4589
+ * A "sound" is the INSTRUMENT plugin's state: default Surge XT round-trips
4590
+ * through the Tracktion ValueTree (get/setPluginState); third-party
4591
+ * instruments (u-he Diva, Serum, …) need their RAW VST3 state
4592
+ * (get/setRawPluginState), which the ValueTree wrapper does not faithfully
4593
+ * preserve. The instrument is the first non-utility plugin on the track.
4594
+ * Matching only 'Surge' silently broke history for custom-instrument tracks
4595
+ * pre-split — hence the dual path.
4596
+ *
4597
+ * @since SDK 2.35.0
4598
+ */
4599
+
4600
+ interface SurgeSoundAdapterOverrides {
4601
+ /** Sound-history cap (default 12 — Surge state blobs are large). */
4602
+ historyMax?: number;
4603
+ /** Drawer action label (default 'Import Preset'). */
4604
+ importSoundLabel?: string;
4605
+ }
4606
+ declare function createSurgeSoundAdapter(host: PluginHost, overrides?: SurgeSoundAdapterOverrides): PanelSoundAdapter;
4607
+
4608
+ /**
4609
+ * useSceneState — Scene-keyed state hook for plugin developers.
4610
+ *
4611
+ * Works like `useState`, but maintains separate state per scene.
4612
+ * When the user switches scenes, the previous scene's state is preserved
4613
+ * and restored when they switch back.
4614
+ *
4615
+ * Returns `[value, setForCurrentScene, setForScene]`:
4616
+ * - `value` — state for the currently active scene
4617
+ * - `setForCurrentScene(v)` — updates state for whatever scene is active at call time
4618
+ * - `setForScene(sceneId, v)` — updates state for a specific scene (for async callbacks)
4619
+ *
4620
+ * Both setters support the functional updater pattern: `prev => next`.
4621
+ *
4622
+ * **Important:** For object/array `initialValue`, hoist to a module-level constant
4623
+ * to keep the setter callbacks referentially stable:
4624
+ * ```ts
4625
+ * const EMPTY: string[] = [];
4626
+ * const [items, setItems, setItemsForScene] = useSceneState(activeSceneId, EMPTY);
4627
+ * ```
4628
+ */
4629
+ type SetSceneState<T> = (value: T | ((prev: T) => T)) => void;
4630
+ type SetSceneStateForScene<T> = (sceneId: string, value: T | ((prev: T) => T)) => void;
4631
+ declare function useSceneState<T>(activeSceneId: string | null, initialValue: T): [T, SetSceneState<T>, SetSceneStateForScene<T>];
4632
+
4633
+ /**
4634
+ * useAnySolo — reactively reports whether ANY track in the project is soloed.
4635
+ *
4636
+ * Solo is cross-panel: when the user solos a track in ANY panel, the engine's
4637
+ * effective-mute model silences every non-soloed track. A panel uses this flag
4638
+ * to DIM its own non-soloed rows without lighting their Mute buttons:
4639
+ *
4640
+ * ```tsx
4641
+ * const anySolo = useAnySolo(host);
4642
+ * // ...
4643
+ * <TrackRow soloedOut={anySolo && !track.runtimeState.solo} ... />
4644
+ * ```
4645
+ *
4646
+ * Refreshes on mount and on every track-state change. `onTrackStateChange`
4647
+ * fires for tracks in ALL panels (not just this plugin's), so a solo toggled in
4648
+ * another panel updates this flag too.
4649
+ */
4650
+
4651
+ declare function useAnySolo(host: Pick<PluginHost, 'isAnySoloActive' | 'onTrackStateChange'>): boolean;
4652
+
4048
4653
  /**
4049
4654
  * Plugin SDK Version
4050
4655
  *
@@ -4053,7 +4658,7 @@ declare function useSoundHistory(applySound: (trackId: string, descriptor: unkno
4053
4658
  * Registry checks semver.gte(PLUGIN_SDK_VERSION, manifest.minHostVersion)
4054
4659
  * during activation and marks incompatible plugins accordingly.
4055
4660
  */
4056
- declare const PLUGIN_SDK_VERSION = "2.34.0";
4661
+ declare const PLUGIN_SDK_VERSION = "2.35.0";
4057
4662
 
4058
4663
  /**
4059
4664
  * FX Preset Definitions
@@ -4201,4 +4806,4 @@ interface PickTopKOptions {
4201
4806
  */
4202
4807
  declare function pickTopKWeighted<T>(scored: ReadonlyArray<ScoredCandidate<T>>, options?: PickTopKOptions): T | null;
4203
4808
 
4204
- export { AUDIO_EFFECTS, AUDIO_EFFECT_LABEL, type AudioEffect, type AudioInputDevice, type BulkAddPlaceholderTrack, type ComposeProgressEvent, type ComposeProgressListener, type ComposeSceneOptions, type ComposeSceneResult, ConfirmDialog, type ConfirmDialogProps, type CreateTrackOptions, type CrossfadeInpaintInput, type CrossfadeLayer, type CrossfadeMeta, CrossfadeModal, type CrossfadeModalProps, type CrossfadePairMeta, type CrossfadeSelection, type CrossfadeSlot, CrossfadeTrackRow, type CrossfadeTrackRowProps, type CrossfadeVolumeCurves, DB_MAX, DB_MIN, DEFAULT_FX_CATEGORY_DETAIL, DEFAULT_FX_DRY_WET, DRAG_DEAD_ZONE, type DeckBoundaryEvent, type DeckBoundaryListener, type DesignerRowSlots, DownloadPackButton, type DownloadPackButtonProps, type DownloadPackButtonVariant, type DrawerTab, type DrumKit, EMPTY_FX_DETAIL_STATE, EMPTY_FX_STATE, EQUAL_POWER_GAIN, type ExportMidiBundleOptions, type ExportMidiBundleResult, type ExportedPluginData, FX_CATEGORIES, FX_CHAIN_ORDER, FX_DISPLAY_LABELS, FX_ENGINE_PLUGIN_NAMES, FX_PRESET_CONFIGS, type FadeDirection, type FadeEntry, type FadeGesture, type FadeLayer, type FadeMeta, FadeModal, type FadeModalProps, type FadeSelection, FadeTrackRow, type FadeTrackRowProps, type FxCategory, type FxCategoryDetailState, type FxPreset, type FxPresetConfig, type FxPresetData, type FxPresetDataEntry, FxToggleBar, type FxToggleBarProps, GUTTER_W, type GeneratorPlugin, type GeneratorType, type ImportCandidateScene, type ImportCandidateTrack, ImportTrackModal, type ImportTrackModalProps, type InstrumentDescriptor, TrackDrawer as InstrumentDrawer, type TrackDrawerProps as InstrumentDrawerProps, type InstrumentSampler, type InstrumentZone, type LLMCandidate, type LLMContent, type LLMFunctionDeclaration, type LLMGenerationConfig, type LLMGenerationRequest, type LLMGenerationResult, type LLMPart, type LLMSystemInstruction, type LLMTool, type LLMToolUseRequest, type LLMToolUseResponse, type LLMUsageMetadata, LevelMeter, type LevelMeterProps, type ListAudioFilesOptions, type ListImportableTracksOptions, type MidiClipData, type MidiWriteResult, type MixInterpolation, Modal, type ModalProps, type MusicalContext, OffsetScrubber, type OffsetScrubberProps, PLUGIN_SDK_VERSION, PX_PER_BEAT, PanSlider, type PeakAnalysis, PianoRollEditor, type PianoRollEditorProps, type PickTopKOptions, type PluginAppTool, type PluginAppToolInputSchema, type PluginAppToolResult, type PluginAudioTextureRequest, type PluginAudioTextureResult, type PluginCapabilities, type PluginChordSegment, type PluginChordTiming, type PluginConcurrentTrackInfo, type PluginCuePoints, type PluginDownloadOptions, PluginError, type PluginErrorCode, type PluginFileDialogOptions, type PluginFxCategoryDetailState, type PluginGenerationContext, type PluginHost, type PluginHttpRequestOptions, type PluginHttpResponse, type PluginManifest, type PluginMidiNote, type PluginPresetData, type PluginPresetInfo, type PluginRegistration, type PluginSampleFilter, type PluginSampleImportResult, type PluginSampleInfo, type PluginSampleTrackInfo, type PluginSceneContext, type PluginSceneInfo, type PluginSettingsSchema, type PluginSettingsStore, type PluginSkill, type PluginSkillInputSchema, type PluginStatus, type PluginStemSplitResult, type PluginStemTrackInfo, type PluginSynthInfo, type PluginTrackFxDetailState, type PluginTrackHandle, type PluginTrackInfo, type PluginTrackLevel, type PluginTrackRuntimeState, type PluginTransportState, type PluginTrimWindow, type PluginUIProps, type PostProcessOptions, RESIZE_HANDLE_PX, ROW_HEIGHT, type ReadMidiClip, type ReadMidiResult, type RecordingChunkFinalizedEvent, type RecordingTargetInfo, type SDKTrackRowProps, SLIDER_UNITY, SamplePackCTACard, type SamplePackCTACardProps, type SamplePackCTACardStatus, type SamplePackCardInfo, type SavePluginPresetOptions, type SceneChangeListener, type SceneFamilyTrack, type ScoredCandidate, ScrollingWaveform, type ScrollingWaveformProps, type SettingDefinition, type ShufflePresetResult, SorceryProgressBar, type SoundHistoryEntry, type StemType, type SynthesizeCuePointsOptions, TEXTURAL_ROLES, TRANSITION_DESIGNER_DRAFT_KEY, TrackDrawer, type TrackDrawerProps, type TrackFxDetailState, type TrackFxState, type TrackLevelsHandle, TrackMeterStrip, type TrackMeterStripProps, type TrackMeterView, TrackRow, type TrackRowDragProps, type TrackSoundHistory, type TrackSoundSnapshot, type TrackStateChangeListener, TransitionDesigner, type TransitionDesignerDraft, type TransitionDesignerProps, type TransitionRowType, type TransportEvent, type TransportEventListener, type UnsubscribeFn, type UseSoundHistoryOptions, type UseSoundHistoryResult, type UseTrackReorderOptions, type UseTrackReorderResult, type VolumeAutomationPoint, VolumeSlider, type WaveformPeaks, WaveformView, type WaveformViewProps, analyzeWavPeak, asAudioEffect, asCrossfadeMeta, asFadeMeta, asTransitionDesignerDraft, buildCrossfadeInpaintPrompt, buildCrossfadeVolumeCurves, buildFadeVolumeCurve, buildRowSlots, calculateTimeBasedTarget, cellToPx, centerScrollTop, computePeaks, dbIdsFromKeys, dbToSlider, defaultFadeGesture, drawWaveform, formatConcurrentTracks, hashString, moveItem, normalizeSlots, padPair, padSlots, parseCrossfadePairs, parseFades, pickTopKWeighted, pitchToName, pxToCell, reconcileSlots, resizeNoteDuration, rowKey, rowType, scorePromptMatch, sliderToDb, slotsEqual, soundIdentity, synthesizeCuePoints, tokenizePrompt, transposeNotes, useAnySolo, useSceneState, useSoundHistory, useTrackLevel, useTrackLevels, useTrackMeter, useTrackReorder, useTransportPlaying };
4809
+ export { AUDIO_EFFECTS, AUDIO_EFFECT_LABEL, type AudioEffect, type AudioInputDevice, type BulkAddPlaceholderTrack, type ComposeProgressEvent, type ComposeProgressListener, type ComposeSceneOptions, type ComposeSceneResult, ConfirmDialog, type ConfirmDialogProps, type CoreTrackHandlers, type CreateTrackOptions, type CrossfadeInpaintInput, type CrossfadeLayer, type CrossfadeMeta, CrossfadeModal, type CrossfadeModalProps, type CrossfadePairMeta, type CrossfadeSelection, type CrossfadeSlot, CrossfadeTrackRow, type CrossfadeTrackRowProps, type CrossfadeVolumeCurves, DB_MAX, DB_MIN, DEFAULT_FX_CATEGORY_DETAIL, DEFAULT_FX_DRY_WET, DRAG_DEAD_ZONE, type DeckBoundaryEvent, type DeckBoundaryListener, type DesignerRowSlots, DownloadPackButton, type DownloadPackButtonProps, type DownloadPackButtonVariant, type DrawerTab, type DrumKit, EMPTY_FX_DETAIL_STATE, EMPTY_FX_STATE, EQUAL_POWER_GAIN, type ExportMidiBundleOptions, type ExportMidiBundleResult, type ExportedPluginData, FX_CATEGORIES, FX_CHAIN_ORDER, FX_DISPLAY_LABELS, FX_ENGINE_PLUGIN_NAMES, FX_PRESET_CONFIGS, type FadeDirection, type FadeEntry, type FadeGesture, type FadeLayer, type FadeMeta, FadeModal, type FadeModalProps, type FadeSelection, FadeTrackRow, type FadeTrackRowProps, type FxCategory, type FxCategoryDetailState, type FxPreset, type FxPresetConfig, type FxPresetData, type FxPresetDataEntry, FxToggleBar, type FxToggleBarProps, GUTTER_W, type GenerationServices, type GeneratorPanelAdapter, type GeneratorPanelCore, GeneratorPanelShell, type GeneratorPanelShellProps, type GeneratorPanelSlots, type GeneratorPlugin, type GeneratorTrackState, type GeneratorType, type GroupParseSpec, type GroupRenderContext, type ImportCandidateScene, type ImportCandidateTrack, ImportTrackModal, type ImportTrackModalProps, type InstrumentDescriptor, TrackDrawer as InstrumentDrawer, type TrackDrawerProps as InstrumentDrawerProps, type InstrumentSampler, type InstrumentZone, type LLMCandidate, type LLMContent, type LLMFunctionDeclaration, type LLMGenerationConfig, type LLMGenerationRequest, type LLMGenerationResult, type LLMNoteResponse, type LLMPart, type LLMSystemInstruction, type LLMTool, type LLMToolUseRequest, type LLMToolUseResponse, type LLMUsageMetadata, LevelMeter, type LevelMeterProps, type ListAudioFilesOptions, type ListImportableTracksOptions, type MidiClipData, type MidiWriteResult, type MixInterpolation, Modal, type ModalProps, type MusicalContext, OffsetScrubber, type OffsetScrubberProps, PLUGIN_SDK_VERSION, PX_PER_BEAT, PanSlider, type PanelFeatureFlags, type PanelGenerationStrategy, type PanelGroupExtension, type PanelIdentity, type PanelShuffleAdapter, type PanelSoundAdapter, type PeakAnalysis, PianoRollEditor, type PianoRollEditorProps, type PickTopKOptions, type PluginAppTool, type PluginAppToolInputSchema, type PluginAppToolResult, type PluginAudioTextureRequest, type PluginAudioTextureResult, type PluginCapabilities, type PluginChordSegment, type PluginChordTiming, type PluginConcurrentTrackInfo, type PluginCuePoints, type PluginDownloadOptions, PluginError, type PluginErrorCode, type PluginFileDialogOptions, type PluginFxCategoryDetailState, type PluginGenerationContext, type PluginHost, type PluginHttpRequestOptions, type PluginHttpResponse, type PluginManifest, type PluginMidiNote, type PluginPresetData, type PluginPresetInfo, type PluginRegistration, type PluginSampleFilter, type PluginSampleImportResult, type PluginSampleInfo, type PluginSampleTrackInfo, type PluginSceneContext, type PluginSceneInfo, type PluginSettingsSchema, type PluginSettingsStore, type PluginSkill, type PluginSkillInputSchema, type PluginStatus, type PluginStemSplitResult, type PluginStemTrackInfo, type PluginSynthInfo, type PluginTrackFxDetailState, type PluginTrackHandle, type PluginTrackInfo, type PluginTrackLevel, type PluginTrackRuntimeState, type PluginTransportState, type PluginTrimWindow, type PluginUIProps, type PostProcessOptions, RESIZE_HANDLE_PX, ROW_HEIGHT, type ReadMidiClip, type ReadMidiResult, type RecordingChunkFinalizedEvent, type RecordingTargetInfo, type ResolveGroupsOptions, type ResolvedCrossfadePair, type ResolvedFade, type ResolvedGroupsResult, type ResolvedTrackGroup, type SDKTrackRowProps, SLIDER_UNITY, SamplePackCTACard, type SamplePackCTACardProps, type SamplePackCTACardStatus, type SamplePackCardInfo, type SavePluginPresetOptions, type SceneChangeListener, type SceneFamilyTrack, type ScoredCandidate, ScrollingWaveform, type ScrollingWaveformProps, type SettingDefinition, type ShufflePresetResult, SorceryProgressBar, type SoundHistoryEntry, type StemType, type SurgeSoundAdapterOverrides, type SynthesizeCuePointsOptions, TEXTURAL_ROLES, TRANSITION_DESIGNER_DRAFT_KEY, TrackDrawer, type TrackDrawerProps, type TrackFxDetailState, type TrackFxState, type TrackGroupMember, type TrackGroupMeta, type TrackLevelsHandle, TrackMeterStrip, type TrackMeterStripProps, type TrackMeterView, TrackRow, type TrackRowDragProps, type TrackSoundHistory, type TrackSoundSnapshot, type TrackStateChangeListener, TransitionDesigner, type TransitionDesignerDraft, type TransitionDesignerProps, type TransitionOps, type TransitionRowType, type TransportEvent, type TransportEventListener, type UnsubscribeFn, type UseGeneratorPanelCoreOptions, type UseSoundHistoryOptions, type UseSoundHistoryResult, type UseTrackReorderOptions, type UseTrackReorderResult, type UseTransitionOpsInputs, type VolumeAutomationPoint, VolumeSlider, type WaveformPeaks, WaveformView, type WaveformViewProps, analyzeWavPeak, asAudioEffect, asCrossfadeMeta, asFadeMeta, asTransitionDesignerDraft, buildCrossfadeInpaintPrompt, buildCrossfadeVolumeCurves, buildFadeVolumeCurve, buildRowSlots, calculateTimeBasedTarget, cellToPx, centerScrollTop, computePeaks, createSurgeSoundAdapter, dbIdsFromKeys, dbToSlider, defaultFadeGesture, drawWaveform, formatConcurrentTracks, hashString, moveItem, newTrackState, normalizeSlots, padPair, padSlots, parseCrossfadePairs, parseFades, parseLLMNoteResponse, parseTrackGroups, pickTopKWeighted, pitchToName, pluginFxToToggleFx, pxToCell, reconcileSlots, resizeNoteDuration, resolveTrackGroups, rowKey, rowType, scorePromptMatch, sliderToDb, slotsEqual, soundIdentity, synthesizeCuePoints, tokenizePrompt, trackDataKey, transposeNotes, useAnySolo, useGeneratorPanelCore, useSceneState, useSoundHistory, useTrackLevel, useTrackLevels, useTrackMeter, useTrackReorder, useTransitionOps, useTransportPlaying };