Skip to content

Add multi-session lifecycle support to the v2 runtime - #548

Merged
gtong-nv merged 14 commits into
mainfrom
dev/gtong/session-management
Sep 3, 2026
Merged

gtong-nv merged 14 commits into
mainfrom
dev/gtong/session-management

Conversation

@gtong-nv

@gtong-nv gtong-nv commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Add multi-session lifecycle support while keeping the application, model
    weights, and client window alive between sessions.

  • Add an ImGui prompt UI for T2V applications that can request new sessions
    before or after inference.

  • Keep UI processing active after model completion and across WebRTC
    reconnects.

  • Make IModelLoop the single source of inference lifecycle state.

  • Suppress the known non-fatal aioice STUN retry race without hiding other
    asyncio errors.

    fixes [Session Runner] Make IO-Thread/UI-Thread reusable and able to restart (end_old+start_new) a ISession #502

@copy-pr-bot

copy-pr-bot Bot commented Aug 31, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@gtong-nv
gtong-nv force-pushed the dev/gtong/session-management branch from f5348d0 to 07b9786 Compare August 31, 2026 21:29
Comment thread flashdreams/flashdreams/api_v2/loop.py
@gtong-nv
gtong-nv marked this pull request as ready for review September 1, 2026 18:28
@gtong-nv

gtong-nv commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator Author

/ok to test cc238c2

@greptile-apps

greptile-apps Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds multi-session lifecycle support to runtime-v2 while retaining application resources, client windows, and model weights between sessions.

  • Centralizes inference completion state in IModelLoop.
  • Adds reusable T2V prompt sessions and continuous ImGui processing.
  • Preserves WebRTC connections and presentation state across session changes.
  • Updates lifecycle, metrics, documentation, and integration tests for the new behavior.

Confidence Score: 3/5

The PR is not safe to merge while an unauthenticated valid WebRTC offer can replace the active browser and gain its video and control capabilities.

The previously reported peer-takeover path remains: the offer handler negotiates any valid request, releases the current peer, and installs the requester as the active video and control peer without an authorization boundary.

Files Needing Attention: flashdreams/flashdreams/runtime_v2/serving/webrtc_server.py

Important Files Changed

Filename Overview
flashdreams/flashdreams/runtime_v2/application_runner.py Extends application execution from a single session to repeated sessions while retaining application and client-window resources.
flashdreams/flashdreams/runtime_v2/session_runner.py Reworks session completion, reset, UI processing, and handoff behavior for multi-session execution.
flashdreams/flashdreams/runtime_v2/serving/webrtc_server.py Keeps signaling and media resources active across sessions and supports peer replacement.
flashdreams/flashdreams/runtime_v2/webrtc_client_window.py Adapts the WebRTC client window to persistent multi-session lifecycle and event timing.
apps/t2v/t2v/application.py Loads the shared model during application initialization and accepts optional per-session prompts.
apps/t2v/t2v/session.py Adds idle prompt sessions, reusable rollout state, and T2V ImGui UI integration.

Sequence Diagram

sequenceDiagram
    participant B as Browser
    participant W as WebRTC Window
    participant R as Application Runner
    participant S as Session Runner
    participant A as Application
    B->>W: Connect and submit input
    W->>R: Persistent client events
    R->>A: Create session
    R->>S: Run session
    S-->>W: Present generated frames
    S-->>R: Model loop finishes
    R->>A: Create replacement session
    R->>S: Run replacement session
    Note over W,A: Client window and application resources remain alive
Loading

Reviews (8): Last reviewed commit: "Keep T2V CPU tests headless" | Re-trigger Greptile

Comment thread flashdreams/flashdreams/runtime_v2/serving/webrtc_server.py Outdated
Comment on lines +765 to +780
existing_peer = self._peer_connection
if existing_peer is not None:
# This server has one client slot. A valid new offer is a page
# refresh or replacement browser and takes ownership of it.
try:
self._buffer_browser_message(
message,
await self._release_peer_connection(existing_peer)
except BaseException:
await self._release_peer_connection(
peer_connection,
detached_video_track=video_track,
)
except ValueError as error:
channel.send(json.dumps({"type": "error", "message": str(error)}))

@channel.on("close")
def on_close() -> None:
if is_reliable_control:
self._record_client_disconnect()
raise

@peer_connection.on("connectionstatechange")
async def on_connectionstatechange() -> None:
self._media_connected.clear()
self._final_video_track_metrics = None
self._peer_connection = peer_connection

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 security Valid offers hijack active peers

If the server is bound to an interface reachable by another principal, any valid unauthenticated offer releases the legitimate peer and becomes the active peer, allowing the replacement browser to send keyboard, mouse, touch, reset, close, and new-session input to the running application.

How this was verified: The unauthenticated offer route unconditionally installs a successfully negotiated replacement peer, whose control-channel messages then pass the active-peer guard.

Knowledge Base Used:

@ArielG-NV ArielG-NV left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments on design.

Comment thread flashdreams/flashdreams/api_v2/client_window.py Outdated
Comment thread flashdreams/flashdreams/api_v2/loop.py Outdated
Comment thread flashdreams/flashdreams/api_v2/loop.py Outdated
Comment on lines +120 to +135
loopResult = ui_loop._begin_run(events, generation)
if loopResult.stop_requested:
stop.set()
return
if loopResult.new_session_request is not None:
next_session_desc = replace(
session_desc,
metadata={
**session_desc.metadata,
**loopResult.new_session_request,
},
)
stop.set()
return
if loopResult.step_index is None or not step_requested:
return

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can begin a run, and then never finish the run or stop the ui_loop? We should be very careful about introducing cases where we can begin something but never end them.

We should potentially think about even making stop flag setting a type of _finish_run for clarity reasons. A run should likely be forced to have a begin/end for debugging/code-readability/code-extensibility reasons.

@gtong-nv gtong-nv Sep 2, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can begin a run, and then never finish the run or stop the ui_loop

For serving, this is actually a valid use case. If we want to stop, we just kill the server/app.
For debugging purpose, yea, it's better to have a flag to stop the UI run even for the unbounded interactive case.
But how should we design the flag? something like --timeout 60 for 1-min run and stop the app entirely?

@ArielG-NV ArielG-NV Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_finish_run should really just be in a finally: block I suppose... and if this is not possible then something is wrong (begin at entry, finish at end)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh I thought you were referring "launching the app, and let the app run forever".
yea, if what we want is matching _begin_run and _finish_run, this makes sense. I will update that

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved _finish_run to finally: block

Comment thread flashdreams/flashdreams/runtime_v2/session_runner.py Outdated
Comment thread flashdreams/flashdreams/t2v_v2/README.md Outdated
Comment thread flashdreams/flashdreams/api_v2/loop.py
Comment thread flashdreams/flashdreams/runtime_v2/session_runner.py Outdated
@gtong-nv

gtong-nv commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator Author

/ok to test 5a0933b

@ArielG-NV ArielG-NV left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor suggestions; PR looks very good now.

Comment thread flashdreams/flashdreams/runtime_v2/session_runner.py Outdated
Comment thread flashdreams/flashdreams/api_v2/loop.py Outdated
@gtong-nv

gtong-nv commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

/ok to test 7750f1c

@ArielG-NV ArielG-NV left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR looks good now, just need to fix failing tests.

gtong-nv and others added 14 commits September 3, 2026 16:41
Signed-off-by: Gangzheng Tong <gtong@nvidia.com>
aioice can run a retry callback after its transaction future has already completed, which produces a non-fatal InvalidStateError. Filter only that exact callback failure on the dedicated WebRTC event loop and delegate every other exception to asyncio.

Signed-off-by: Gangzheng Tong <gtong@nvidia.com>
Move prompt-driven session replacement into the application UI and keep the runtime UI loop responsive before and after model inference. Model completion no longer implicitly terminates a session; lifecycle events, UI completion, explicit limits, and failures remain terminal.

Signed-off-by: Gangzheng Tong <gtong@nvidia.com>
Let each model loop track its own inference lifecycle and have UI loops query that single source of truth. Initialize the state through the common loop registration path and remove the redundant session-runner wrapper.

Signed-off-by: Gangzheng Tong <gtong@nvidia.com>
Parse and fully negotiate replacement offers before releasing the active peer. Serialize offer swaps and clean up failed candidates without disconnecting the connected browser.

Signed-off-by: Gangzheng Tong <gtong@nvidia.com>
Let UI loops request a fully resolved SessionDesc and have run_session forward it unchanged. This allows replacement sessions to modify any description field instead of only merging metadata.

Signed-off-by: Gangzheng Tong <gtong@nvidia.com>
Signed-off-by: Gangzheng Tong <gtong@nvidia.com>
Signed-off-by: Gangzheng Tong <gtong@nvidia.com>
Signed-off-by: Gangzheng Tong <gtong@nvidia.com>
Signed-off-by: Gangzheng Tong <gtong@nvidia.com>
Co-authored-by: ArielG-NV <159081215+ArielG-NV@users.noreply.github.com>
Signed-off-by: Gangzheng Tong <tonggangzheng@gmail.com>
Signed-off-by: Gangzheng Tong <gtong@nvidia.com>
Signed-off-by: Gangzheng Tong <gtong@nvidia.com>
Signed-off-by: Gangzheng Tong <gtong@nvidia.com>
@gtong-nv
gtong-nv force-pushed the dev/gtong/session-management branch from a0c9e56 to 5d48dcc Compare September 3, 2026 16:59
@ArielG-NV

Copy link
Copy Markdown
Collaborator

/ok to test 5d48dcc

@gtong-nv
gtong-nv added this pull request to the merge queue Sep 3, 2026
Merged via the queue into main with commit 41846b7 Sep 3, 2026
9 checks passed
@gtong-nv
gtong-nv deleted the dev/gtong/session-management branch September 3, 2026 18:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Session Runner] Make IO-Thread/UI-Thread reusable and able to restart (end_old+start_new) a ISession

2 participants