@xmaxai/sdk 0.1.0 → 1.0.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.
@@ -1,2 +1,2 @@
1
- export { D as DragTrackController, a as DragTrackControllerOptions, R as RealtimeConnectOptions, b as RealtimeInitialState, c as RealtimeModel, d as RealtimePrewarmHandle, e as RealtimePromptState, f as RealtimeRestartOptions, g as RealtimeSession, h as RealtimeSetImageOptions, i as RealtimeSetInput, j as RealtimeSetModeOptions, k as RemoteViewHost, X as XmaxClient, l as XmaxClientFiles, m as XmaxClientOptions, n as XmaxRealtimeSession, o as createDragTrackController, q as createRemoteViewHost, r as createXmaxClient, s as getContentRect, t as mapTargetPointToCanvas, u as mapViewportPointToCoordinateSpace, v as models, w as observeDragSurfaceVideoSync, y as syncDragSurfaceToVideo } from '../index-Dai62Sos.cjs';
1
+ export { D as DragTrackController, a as DragTrackControllerOptions, R as RealtimeConnectOptions, b as RealtimeInitialState, c as RealtimeModel, d as RealtimePrewarmHandle, e as RealtimePromptState, f as RealtimeRestartOptions, g as RealtimeSession, h as RealtimeSetImageOptions, i as RealtimeSetInput, j as RealtimeSetModeOptions, k as RemoteViewHost, X as XmaxClient, l as XmaxClientFiles, m as XmaxClientOptions, n as XmaxRealtimeSession, o as createDragTrackController, q as createRemoteViewHost, r as createXmaxClient, s as getContentRect, t as mapTargetPointToCanvas, u as mapViewportPointToCoordinateSpace, v as models, w as observeDragSurfaceVideoSync, y as syncDragSurfaceToVideo } from '../index-Dg1ElHAj.cjs';
2
2
  import '../rtc-manager-gYDkADGw.cjs';
@@ -1,2 +1,2 @@
1
- export { D as DragTrackController, a as DragTrackControllerOptions, R as RealtimeConnectOptions, b as RealtimeInitialState, c as RealtimeModel, d as RealtimePrewarmHandle, e as RealtimePromptState, f as RealtimeRestartOptions, g as RealtimeSession, h as RealtimeSetImageOptions, i as RealtimeSetInput, j as RealtimeSetModeOptions, k as RemoteViewHost, X as XmaxClient, l as XmaxClientFiles, m as XmaxClientOptions, n as XmaxRealtimeSession, o as createDragTrackController, q as createRemoteViewHost, r as createXmaxClient, s as getContentRect, t as mapTargetPointToCanvas, u as mapViewportPointToCoordinateSpace, v as models, w as observeDragSurfaceVideoSync, y as syncDragSurfaceToVideo } from '../index-BIUk_kvb.js';
1
+ export { D as DragTrackController, a as DragTrackControllerOptions, R as RealtimeConnectOptions, b as RealtimeInitialState, c as RealtimeModel, d as RealtimePrewarmHandle, e as RealtimePromptState, f as RealtimeRestartOptions, g as RealtimeSession, h as RealtimeSetImageOptions, i as RealtimeSetInput, j as RealtimeSetModeOptions, k as RemoteViewHost, X as XmaxClient, l as XmaxClientFiles, m as XmaxClientOptions, n as XmaxRealtimeSession, o as createDragTrackController, q as createRemoteViewHost, r as createXmaxClient, s as getContentRect, t as mapTargetPointToCanvas, u as mapViewportPointToCoordinateSpace, v as models, w as observeDragSurfaceVideoSync, y as syncDragSurfaceToVideo } from '../index-Cw8C8LbO.js';
2
2
  import '../rtc-manager-gYDkADGw.js';
@@ -1,5 +1,5 @@
1
- export { RealtimePrewarmHandle, RealtimeSession, createRemoteViewHost, createXmaxClient, observeDragSurfaceVideoSync, syncDragSurfaceToVideo } from '../chunk-74ZZWUPI.js';
2
- export { createDragTrackController, getContentRect, mapTargetPointToCanvas, mapViewportPointToCoordinateSpace, models } from '../chunk-67XSD3QJ.js';
3
- import '../chunk-PLU2YVAS.js';
1
+ export { RealtimePrewarmHandle, RealtimeSession, createRemoteViewHost, createXmaxClient, observeDragSurfaceVideoSync, syncDragSurfaceToVideo } from '../chunk-VLJZ56PT.js';
2
+ export { createDragTrackController, getContentRect, mapTargetPointToCanvas, mapViewportPointToCoordinateSpace, models } from '../chunk-V4NR6CPP.js';
3
+ import '../chunk-LCPC56BK.js';
4
4
  //# sourceMappingURL=index.js.map
5
5
  //# sourceMappingURL=index.js.map
@@ -91,8 +91,13 @@ type RealtimeInitialState = {
91
91
  autoStart?: boolean;
92
92
  /** @internal Business model label in RTC start params; optional — SDK uses a default when omitted. */
93
93
  model?: string;
94
- /** MoX instant — static image generation that follows drag tracks; sent as `static_generate`. */
94
+ /** MoX instant — when `true`, sent as `static_generate` on connect start only (never cached). */
95
95
  staticGenerate?: boolean;
96
+ /**
97
+ * MoX instant — uploaded source still URL (COS). Sent as `static_image_path` on connect
98
+ * start only (never cached). Local RTC publish is still used for preview / room compatibility.
99
+ */
100
+ staticImagePath?: string;
96
101
  };
97
102
  type RealtimeConnectOptions = {
98
103
  model: RealtimeModel;
@@ -126,8 +131,18 @@ type RealtimeRestartOptions = {
126
131
  /** @internal Optional business model label; SDK uses a default when omitted. */
127
132
  model?: string;
128
133
  size?: [number, number];
129
- /** MoX instant — static image generation that follows drag tracks; sent as `static_generate`. */
134
+ /**
135
+ * MoX instant — when `true`, sent as `static_generate` on this start only (never cached).
136
+ * Omit on non-Instant starts.
137
+ */
130
138
  staticGenerate?: boolean;
139
+ /**
140
+ * MoX instant — COS URL sent as `static_image_path` on this start only (never cached).
141
+ * Omit on non-Instant starts.
142
+ */
143
+ staticImagePath?: string;
144
+ /** Keep the last rendered remote frame visible while waiting for the next start output. */
145
+ preserveRemoteOutput?: boolean;
131
146
  };
132
147
  /** @deprecated Use {@link RealtimeRestartOptions} */
133
148
  type RealtimeSetModeOptions = RealtimeRestartOptions;
@@ -207,7 +222,6 @@ declare class RealtimeSession implements XmaxRealtimeSession {
207
222
  private localVideoSize;
208
223
  private currentPrompt;
209
224
  private currentGenerationModel;
210
- private currentStaticGenerate;
211
225
  private disconnected;
212
226
  private remoteViewHost;
213
227
  private dragController;
@@ -259,19 +273,23 @@ type DragTrackControllerOptions = {
259
273
  fitMode?: 'contain' | 'cover';
260
274
  mirrored?: boolean;
261
275
  enabled?: boolean;
262
- /** When idle (no active pointers), still emit `onTracks([])` on each sample tick. */
263
- emitEmptyTracksWhenIdle?: boolean;
264
276
  onTracks: (tracks: Array<[number, number]>) => void | Promise<void>;
277
+ /** Fired once when a real drag stroke begins (first pointer down). */
278
+ onStrokeStart?: () => void | Promise<void>;
279
+ /** Fired once when a real drag stroke ends (pointer up/cancel), not on disable/destroy. */
280
+ onStrokeEnd?: () => void | Promise<void>;
265
281
  };
266
282
  declare class DragTrackController {
267
283
  private readonly container;
268
284
  private readonly canvas;
269
285
  private readonly onTracks;
286
+ private readonly onStrokeStart;
287
+ private readonly onStrokeEnd;
288
+ private strokeActive;
270
289
  private targetSize;
271
290
  private fitMode;
272
291
  private mirrored;
273
292
  private enabled;
274
- private emitEmptyTracksWhenIdle;
275
293
  private readonly activePointers;
276
294
  private readonly lastTargetPoints;
277
295
  private readonly segQueue;
@@ -286,7 +304,6 @@ declare class DragTrackController {
286
304
  private readonly onPointerCancel;
287
305
  constructor(container: HTMLElement, options: DragTrackControllerOptions);
288
306
  setEnabled(enabled: boolean): void;
289
- setEmitEmptyTracksWhenIdle(emitEmptyTracksWhenIdle: boolean): void;
290
307
  setTargetSize(targetSize: [number, number]): void;
291
308
  setFitMode(fitMode: 'contain' | 'cover'): void;
292
309
  setMirrored(mirrored: boolean): void;
@@ -91,8 +91,13 @@ type RealtimeInitialState = {
91
91
  autoStart?: boolean;
92
92
  /** @internal Business model label in RTC start params; optional — SDK uses a default when omitted. */
93
93
  model?: string;
94
- /** MoX instant — static image generation that follows drag tracks; sent as `static_generate`. */
94
+ /** MoX instant — when `true`, sent as `static_generate` on connect start only (never cached). */
95
95
  staticGenerate?: boolean;
96
+ /**
97
+ * MoX instant — uploaded source still URL (COS). Sent as `static_image_path` on connect
98
+ * start only (never cached). Local RTC publish is still used for preview / room compatibility.
99
+ */
100
+ staticImagePath?: string;
96
101
  };
97
102
  type RealtimeConnectOptions = {
98
103
  model: RealtimeModel;
@@ -126,8 +131,18 @@ type RealtimeRestartOptions = {
126
131
  /** @internal Optional business model label; SDK uses a default when omitted. */
127
132
  model?: string;
128
133
  size?: [number, number];
129
- /** MoX instant — static image generation that follows drag tracks; sent as `static_generate`. */
134
+ /**
135
+ * MoX instant — when `true`, sent as `static_generate` on this start only (never cached).
136
+ * Omit on non-Instant starts.
137
+ */
130
138
  staticGenerate?: boolean;
139
+ /**
140
+ * MoX instant — COS URL sent as `static_image_path` on this start only (never cached).
141
+ * Omit on non-Instant starts.
142
+ */
143
+ staticImagePath?: string;
144
+ /** Keep the last rendered remote frame visible while waiting for the next start output. */
145
+ preserveRemoteOutput?: boolean;
131
146
  };
132
147
  /** @deprecated Use {@link RealtimeRestartOptions} */
133
148
  type RealtimeSetModeOptions = RealtimeRestartOptions;
@@ -207,7 +222,6 @@ declare class RealtimeSession implements XmaxRealtimeSession {
207
222
  private localVideoSize;
208
223
  private currentPrompt;
209
224
  private currentGenerationModel;
210
- private currentStaticGenerate;
211
225
  private disconnected;
212
226
  private remoteViewHost;
213
227
  private dragController;
@@ -259,19 +273,23 @@ type DragTrackControllerOptions = {
259
273
  fitMode?: 'contain' | 'cover';
260
274
  mirrored?: boolean;
261
275
  enabled?: boolean;
262
- /** When idle (no active pointers), still emit `onTracks([])` on each sample tick. */
263
- emitEmptyTracksWhenIdle?: boolean;
264
276
  onTracks: (tracks: Array<[number, number]>) => void | Promise<void>;
277
+ /** Fired once when a real drag stroke begins (first pointer down). */
278
+ onStrokeStart?: () => void | Promise<void>;
279
+ /** Fired once when a real drag stroke ends (pointer up/cancel), not on disable/destroy. */
280
+ onStrokeEnd?: () => void | Promise<void>;
265
281
  };
266
282
  declare class DragTrackController {
267
283
  private readonly container;
268
284
  private readonly canvas;
269
285
  private readonly onTracks;
286
+ private readonly onStrokeStart;
287
+ private readonly onStrokeEnd;
288
+ private strokeActive;
270
289
  private targetSize;
271
290
  private fitMode;
272
291
  private mirrored;
273
292
  private enabled;
274
- private emitEmptyTracksWhenIdle;
275
293
  private readonly activePointers;
276
294
  private readonly lastTargetPoints;
277
295
  private readonly segQueue;
@@ -286,7 +304,6 @@ declare class DragTrackController {
286
304
  private readonly onPointerCancel;
287
305
  constructor(container: HTMLElement, options: DragTrackControllerOptions);
288
306
  setEnabled(enabled: boolean): void;
289
- setEmitEmptyTracksWhenIdle(emitEmptyTracksWhenIdle: boolean): void;
290
307
  setTargetSize(targetSize: [number, number]): void;
291
308
  setFitMode(fitMode: 'contain' | 'cover'): void;
292
309
  setMirrored(mirrored: boolean): void;
package/dist/index.cjs CHANGED
@@ -1278,7 +1278,8 @@ var XmaxOpenClient = class {
1278
1278
  return p.data;
1279
1279
  }
1280
1280
  const mappedMessage = resolveApiErrorMessage(p.code, this.i18n.locale);
1281
- const errorMessage = mappedMessage ?? this.i18n.t("errors.requestRetry");
1281
+ const backendMessage = typeof p.message === "string" && p.message.trim() ? p.message.trim() : void 0;
1282
+ const errorMessage = mappedMessage ?? backendMessage ?? this.i18n.t("errors.requestRetry");
1282
1283
  throw new Error(errorMessage);
1283
1284
  } catch (error) {
1284
1285
  if (this.isAbortError(error)) {
@@ -1430,6 +1431,7 @@ function createStartRtcRoomEvent(input) {
1430
1431
  const resolvedPrompt = input.prompt?.trim() ?? "";
1431
1432
  const refImagePath = input.refImagePath?.trim() || input.refImage?.trim() || void 0;
1432
1433
  const useRefImage = !!refImagePath;
1434
+ const staticImagePath = input.staticImagePath?.trim() || void 0;
1433
1435
  return {
1434
1436
  event: "start",
1435
1437
  user_id: input.userId?.trim() || void 0,
@@ -1441,7 +1443,9 @@ function createStartRtcRoomEvent(input) {
1441
1443
  prompt: resolvedPrompt,
1442
1444
  ref_image_path: useRefImage ? refImagePath : void 0,
1443
1445
  ref_image: useRefImage ? refImagePath : void 0,
1444
- static_generate: input.staticGenerate === void 0 ? void 0 : input.staticGenerate,
1446
+ // Instant-only omit when false/undefined so non-instant starts never carry leftover flags.
1447
+ static_generate: input.staticGenerate === true ? true : void 0,
1448
+ static_image_path: staticImagePath,
1445
1449
  ...input.extraParams ?? {}
1446
1450
  }
1447
1451
  };
@@ -1727,7 +1731,7 @@ var _RtcManager = class _RtcManager {
1727
1731
  this.lastRemoteSei = null;
1728
1732
  this.lastRemoteSeiUserId = null;
1729
1733
  this.hasLoggedSeiSendFailure = false;
1730
- if (previousExpectedRemoteSei !== this.expectedRemoteSei && this.remoteVideoUserId) {
1734
+ if (previousExpectedRemoteSei !== this.expectedRemoteSei && this.remoteVideoUserId && !this.preserveRemoteDom) {
1731
1735
  this.pendingRemoteVideoUserId = this.remoteVideoUserId;
1732
1736
  this.remoteVideoUserId = null;
1733
1737
  }
@@ -3776,6 +3780,7 @@ function drawNeon(ctx, segs, container, targetSize, dpr, fitMode, mirrored) {
3776
3780
  }
3777
3781
  var DragTrackController = class {
3778
3782
  constructor(container, options) {
3783
+ this.strokeActive = false;
3779
3784
  this.activePointers = /* @__PURE__ */ new Map();
3780
3785
  this.lastTargetPoints = /* @__PURE__ */ new Map();
3781
3786
  this.segQueue = [];
@@ -3785,11 +3790,12 @@ var DragTrackController = class {
3785
3790
  this.resizeObserver = null;
3786
3791
  this.container = container;
3787
3792
  this.onTracks = options.onTracks;
3793
+ this.onStrokeStart = options.onStrokeStart;
3794
+ this.onStrokeEnd = options.onStrokeEnd;
3788
3795
  this.targetSize = options.targetSize;
3789
3796
  this.fitMode = options.fitMode ?? "cover";
3790
3797
  this.mirrored = options.mirrored ?? false;
3791
3798
  this.enabled = options.enabled ?? true;
3792
- this.emitEmptyTracksWhenIdle = options.emitEmptyTracksWhenIdle ?? false;
3793
3799
  this.canvas = document.createElement("canvas");
3794
3800
  this.canvas.className = "Xmax-drag-track-canvas";
3795
3801
  this.canvas.style.cssText = "position:absolute;inset:0;z-index:21;width:100%;height:100%;pointer-events:none;";
@@ -3803,32 +3809,12 @@ var DragTrackController = class {
3803
3809
  this.bindResizeObserver();
3804
3810
  this.bindPointerEvents();
3805
3811
  this.applyInteractionStyle();
3806
- if (this.enabled && this.emitEmptyTracksWhenIdle) {
3807
- this.startSampling();
3808
- }
3809
3812
  }
3810
3813
  setEnabled(enabled) {
3811
3814
  this.enabled = enabled;
3812
3815
  this.applyInteractionStyle();
3813
3816
  if (!enabled) {
3814
- this.finishStroke({ stopIdleSampling: true });
3815
- return;
3816
- }
3817
- if (this.emitEmptyTracksWhenIdle && this.activePointers.size === 0) {
3818
- this.startSampling();
3819
- }
3820
- }
3821
- setEmitEmptyTracksWhenIdle(emitEmptyTracksWhenIdle) {
3822
- if (this.emitEmptyTracksWhenIdle === emitEmptyTracksWhenIdle) {
3823
- return;
3824
- }
3825
- this.emitEmptyTracksWhenIdle = emitEmptyTracksWhenIdle;
3826
- if (emitEmptyTracksWhenIdle && this.enabled && this.activePointers.size === 0) {
3827
- this.startSampling();
3828
- return;
3829
- }
3830
- if (!emitEmptyTracksWhenIdle && this.activePointers.size === 0) {
3831
- this.stopSampling();
3817
+ this.finishStroke();
3832
3818
  }
3833
3819
  }
3834
3820
  setTargetSize(targetSize) {
@@ -3841,7 +3827,7 @@ var DragTrackController = class {
3841
3827
  this.mirrored = mirrored;
3842
3828
  }
3843
3829
  destroy() {
3844
- this.finishStroke({ stopIdleSampling: true });
3830
+ this.finishStroke();
3845
3831
  this.unbindPointerEvents();
3846
3832
  this.unbindResizeObserver();
3847
3833
  this.canvas.remove();
@@ -3958,7 +3944,7 @@ var DragTrackController = class {
3958
3944
  return;
3959
3945
  }
3960
3946
  const tracks = this.collectCurrentTracks();
3961
- if (!tracks.length && !this.emitEmptyTracksWhenIdle) {
3947
+ if (!tracks.length) {
3962
3948
  return;
3963
3949
  }
3964
3950
  this.sampleInFlight = true;
@@ -3976,14 +3962,17 @@ var DragTrackController = class {
3976
3962
  this.flushTracks();
3977
3963
  }, 30);
3978
3964
  }
3979
- finishStroke(options) {
3980
- const stopIdleSampling = options?.stopIdleSampling ?? !this.emitEmptyTracksWhenIdle;
3981
- if (stopIdleSampling) {
3982
- this.stopSampling();
3983
- }
3965
+ finishStroke(emitEnd = false) {
3966
+ const wasActive = this.strokeActive;
3967
+ this.strokeActive = false;
3968
+ this.stopSampling();
3984
3969
  this.stopDrawLoop();
3985
3970
  this.segQueue.length = 0;
3986
3971
  this.clearCanvas();
3972
+ if (emitEnd && wasActive && this.onStrokeEnd) {
3973
+ Promise.resolve(this.onStrokeEnd()).catch(() => {
3974
+ });
3975
+ }
3987
3976
  }
3988
3977
  handlePointerDown(e) {
3989
3978
  if (!this.enabled) {
@@ -4007,6 +3996,12 @@ var DragTrackController = class {
4007
3996
  if (targetPoint) {
4008
3997
  this.lastTargetPoints.set(e.pointerId, targetPoint);
4009
3998
  }
3999
+ const strokeWasActive = this.strokeActive;
4000
+ this.strokeActive = true;
4001
+ if (!strokeWasActive && this.onStrokeStart) {
4002
+ Promise.resolve(this.onStrokeStart()).catch(() => {
4003
+ });
4004
+ }
4010
4005
  this.startDrawLoop();
4011
4006
  this.startSampling();
4012
4007
  }
@@ -4039,7 +4034,7 @@ var DragTrackController = class {
4039
4034
  } catch {
4040
4035
  }
4041
4036
  if (this.activePointers.size === 0) {
4042
- this.finishStroke();
4037
+ this.finishStroke(true);
4043
4038
  }
4044
4039
  }
4045
4040
  handlePointerCancel(e) {
@@ -4049,7 +4044,7 @@ var DragTrackController = class {
4049
4044
  this.activePointers.delete(e.pointerId);
4050
4045
  this.lastTargetPoints.delete(e.pointerId);
4051
4046
  if (this.activePointers.size === 0) {
4052
- this.finishStroke();
4047
+ this.finishStroke(true);
4053
4048
  }
4054
4049
  }
4055
4050
  };
@@ -4223,7 +4218,6 @@ var RealtimeSession = class _RealtimeSession {
4223
4218
  this.localVideoSize = null;
4224
4219
  this.currentPrompt = "";
4225
4220
  this.currentGenerationModel = "";
4226
- this.currentStaticGenerate = void 0;
4227
4221
  this.disconnected = false;
4228
4222
  this.remoteViewHost = null;
4229
4223
  this.dragController = null;
@@ -4359,7 +4353,6 @@ var RealtimeSession = class _RealtimeSession {
4359
4353
  const initialState = options.initialState;
4360
4354
  this.currentPrompt = resolvePromptText(initialState?.prompt);
4361
4355
  this.currentGenerationModel = resolveGenerationModel(initialState?.model);
4362
- this.currentStaticGenerate = initialState?.staticGenerate;
4363
4356
  const publishFpsOptions = {
4364
4357
  mobile: options.mobile,
4365
4358
  highQuality: true,
@@ -4386,7 +4379,8 @@ var RealtimeSession = class _RealtimeSession {
4386
4379
  model: this.currentGenerationModel || void 0,
4387
4380
  size: options.size,
4388
4381
  refImage: initialRefImageUrl,
4389
- staticGenerate: this.currentStaticGenerate
4382
+ staticGenerate: initialState?.staticGenerate,
4383
+ staticImagePath: initialState?.staticImagePath?.trim() || void 0
4390
4384
  });
4391
4385
  }
4392
4386
  }
@@ -4465,15 +4459,14 @@ var RealtimeSession = class _RealtimeSession {
4465
4459
  if (options?.model !== void 0) {
4466
4460
  this.currentGenerationModel = resolveGenerationModel(options.model);
4467
4461
  }
4468
- if (options?.staticGenerate !== void 0) {
4469
- this.currentStaticGenerate = options.staticGenerate;
4470
- }
4471
4462
  await this.runStart({
4472
4463
  prompt: this.currentPrompt || void 0,
4473
4464
  model: this.currentGenerationModel || void 0,
4474
4465
  size: options?.size,
4475
4466
  refImage: resolvedRefImage,
4476
- staticGenerate: this.currentStaticGenerate
4467
+ staticGenerate: options?.staticGenerate === true ? true : void 0,
4468
+ staticImagePath: options?.staticImagePath?.trim() || void 0,
4469
+ preserveRemoteOutput: options?.preserveRemoteOutput
4477
4470
  });
4478
4471
  } catch (error) {
4479
4472
  this.reportError(error);
@@ -4564,17 +4557,20 @@ var RealtimeSession = class _RealtimeSession {
4564
4557
  if (!this.rtc.snapshot.joined) {
4565
4558
  return;
4566
4559
  }
4560
+ const preserveRemoteOutput = options.preserveRemoteOutput ?? false;
4561
+ if (preserveRemoteOutput) {
4562
+ this.rtc.setPreserveRemoteDom(true);
4563
+ }
4567
4564
  const startPrompt = options.prompt?.trim() ?? this.currentPrompt;
4568
4565
  if (options.model !== void 0) {
4569
4566
  this.currentGenerationModel = resolveGenerationModel(options.model);
4570
4567
  }
4571
- if (options.staticGenerate !== void 0) {
4572
- this.currentStaticGenerate = options.staticGenerate;
4573
- }
4574
4568
  const modelLabel = resolveGenerationModel(this.currentGenerationModel);
4575
4569
  await this.rtc.ensurePublishedInputBeforeStart();
4576
- this.rtc.setRemoteVideoContainer(null);
4577
- this.rtc.clearRemoteVideo();
4570
+ if (!preserveRemoteOutput) {
4571
+ this.rtc.setRemoteVideoContainer(null);
4572
+ this.rtc.clearRemoteVideo();
4573
+ }
4578
4574
  const size = resolveSessionTargetSize({
4579
4575
  localVideoSize: this.localVideoSize,
4580
4576
  overrideSize: options.size ?? this.sessionSizeOverride
@@ -4595,16 +4591,21 @@ var RealtimeSession = class _RealtimeSession {
4595
4591
  size,
4596
4592
  prompt: startPrompt,
4597
4593
  refImagePath: resolveRefImagePath(options.refImage),
4598
- staticGenerate: this.currentStaticGenerate
4594
+ // Never reuse prior start — caller must pass Instant fields each time.
4595
+ staticGenerate: options.staticGenerate === true ? true : void 0,
4596
+ staticImagePath: options.staticImagePath?.trim() || void 0
4599
4597
  });
4600
- console.log("[Xmax SDK] \u771F\u5B9E\u53D1\u9001 start ->", startRoomEvent);
4601
4598
  await this.rtc.sendRoomEvent(startRoomEvent);
4602
- await this.rtc.refreshRemoteVideoBinding({ force: true });
4599
+ await this.rtc.refreshRemoteVideoBinding({ force: !preserveRemoteOutput });
4603
4600
  this.updateDragController(true);
4604
4601
  this.scheduleNotifyRemoteStream();
4605
4602
  } catch (error) {
4606
4603
  this.rtc.configureSessionSei(null);
4607
4604
  throw error;
4605
+ } finally {
4606
+ if (preserveRemoteOutput) {
4607
+ this.rtc.setPreserveRemoteDom(false);
4608
+ }
4608
4609
  }
4609
4610
  }
4610
4611
  isDragEnabled() {
@@ -4731,7 +4732,6 @@ var RealtimeSession = class _RealtimeSession {
4731
4732
  this.taskUid = null;
4732
4733
  this.currentPrompt = "";
4733
4734
  this.currentGenerationModel = "";
4734
- this.currentStaticGenerate = void 0;
4735
4735
  this.sessionTargetSize = null;
4736
4736
  this.dragController?.destroy();
4737
4737
  this.dragController = null;