Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
762da54
Add public demo application contracts
jarcherNV Aug 13, 2026
991b66e
Fix linter issues
jarcherNV Aug 13, 2026
72afb61
Add public demo Runner facade
jarcherNV Aug 13, 2026
04a450d
Fix public demo application lifecycle
jarcherNV Aug 13, 2026
cd7f35d
Add public demo IO handler factories
jarcherNV Aug 13, 2026
d118f9e
Adopt public demo Runner in app launch path
jarcherNV Aug 13, 2026
433fd03
Ensure public demo Runner always closes applications
jarcherNV Aug 13, 2026
3b56a0f
Fix public demo cleanup type-check issues
jarcherNV Aug 13, 2026
9bea150
Preserve runner failures during cleanup
jarcherNV Aug 13, 2026
e477546
Unify demo session stop conditions
jarcherNV Aug 13, 2026
baf8578
Harden public demo runner cleanup
jarcherNV Aug 13, 2026
fadac4c
Add named pull input state API
jarcherNV Aug 13, 2026
0ad73e5
Shield async public runner cleanup
jarcherNV Aug 13, 2026
485a9bd
Add output comparison sink
jarcherNV Aug 13, 2026
865f2fa
Preserve runner BaseException failures during cleanup
jarcherNV Aug 13, 2026
d66a8b5
Simplify demo application discovery
jarcherNV Aug 13, 2026
6247dd7
Propagate replay schemas through demo runner
jarcherNV Aug 13, 2026
c6c2dd4
Migrate T2V replay to public demo runner
jarcherNV Aug 13, 2026
a85048c
Extract neutral T2V demo shell
jarcherNV Aug 13, 2026
c571b86
Add integration-owned T2V app entries
jarcherNV Aug 13, 2026
1df1e7e
Remove duplicated T2V demo preset registry
jarcherNV Aug 13, 2026
aa69c9b
Fix public runner cleanup edge cases
jarcherNV Aug 13, 2026
571dd02
Move T2V replay launch into shared demo helper
jarcherNV Aug 13, 2026
c2916fa
Close public apps from RuntimeHost shutdown
jarcherNV Aug 13, 2026
9d7f108
Launch public apps directly from flashdreams-run
jarcherNV Aug 13, 2026
b9e80ab
Add direct WebRTC launch for public T2V apps
jarcherNV Aug 13, 2026
223bf4b
Clean up direct WebRTC app startup failures
jarcherNV Aug 13, 2026
83449e6
Add wan21 and wan22 T2V apps with usage README
jarcherNV Aug 13, 2026
a1c0764
Close apps when external runtime host is already closed
jarcherNV Aug 13, 2026
2e13082
Harden WebRTC manager shutdown cleanup
jarcherNV Aug 13, 2026
36a2a5c
Avoid off-worker app cleanup after closed host
jarcherNV Aug 13, 2026
5b11641
Document external host cleanup contract
jarcherNV Aug 13, 2026
cd3e361
Clean up WebRTC distributed state on startup failure
jarcherNV Aug 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions flashdreams/flashdreams/demo/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

"""Public demo application authoring API."""

from flashdreams.demo.application import (
Application,
ApplicationSession,
DemoAdapterApplication,
FrameOutputSink,
IApplication,
IApplicationSession,
InferenceSessionApplicationAdapter,
IOHandler,
IOutputSink,
RuntimeOutputSinkFrameAdapter,
)

__all__ = [
"Application",
"ApplicationSession",
"DemoAdapterApplication",
"FrameOutputSink",
"IApplication",
"IApplicationSession",
"IOutputSink",
"IOHandler",
"InferenceSessionApplicationAdapter",
"RuntimeOutputSinkFrameAdapter",
]
254 changes: 254 additions & 0 deletions flashdreams/flashdreams/demo/application.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

"""Public demo application contracts.

This module is the author-facing facade above ``flashdreams.runtime.demo``. The
runtime package owns execution, providers, sinks, drivers, and worker affinity;
these protocols name the smaller surface demo applications should eventually
implement directly.
"""

from __future__ import annotations

from collections.abc import Sequence
from dataclasses import dataclass, field
from typing import Any, Protocol, runtime_checkable

from flashdreams.runtime.config import InferenceConfig
from flashdreams.runtime.demo.outputs import (
OutputDecision,
OutputSink,
SessionInfo,
)
from flashdreams.runtime.demo.session_inputs import UserInputWindow
from flashdreams.runtime.demo.spec import DemoAdapter, DemoSpec, PreparedScenario
from flashdreams.runtime.inputs import InferenceInput
from flashdreams.runtime.interfaces import InferenceRuntime, InferenceSession
from flashdreams.runtime.output import OutputArtifact
from flashdreams.runtime.types import (
StepRequest,
StepRequirements,
StepResult,
step_requirements_from_request,
)


@runtime_checkable
class ApplicationSession(Protocol):
"""One model session exposed through the public demo API."""

def init(self) -> None:
"""Initialize per-session resources before the first step."""
...

def session_info(self) -> SessionInfo:
"""Return output-facing metadata known after session setup."""
...

def next_step_requirements(self) -> StepRequirements | None:
"""Return requirements for the next step, or ``None`` when complete."""
...

def step(self, model_input: InferenceInput) -> StepResult:
"""Run one inference step from model-facing inputs."""
...

def reset(self, model_input: InferenceInput | None = None) -> None:
"""Reset rollout state when the backend supports it."""
...

def close(self) -> None:
"""Release per-session resources."""
...


@runtime_checkable
class Application(Protocol):
"""Public demo application facade."""

def init(self, launch_args: Sequence[str]) -> None:
"""Initialize application-level launch state."""
...

def create_session(self) -> ApplicationSession:
"""Create one model session.

Public runners must call this on the same worker that will execute the
session so model construction and stepping share worker affinity.
"""
...

Comment thread
greptile-apps[bot] marked this conversation as resolved.

@runtime_checkable
class IOHandler(Protocol):
"""Public facade over runtime input, output, and transport edges."""

def open(self, session_info: SessionInfo) -> None:
"""Prepare input/output resources after session setup."""
...

def next_window(self, requirements: StepRequirements) -> UserInputWindow:
"""Return the user-input window selected for one model step.

Model-specific conversion from this window to ``InferenceInput`` remains
the responsibility of ``ModelInputProvider`` in the runtime layer.
"""
...

def get_user_input_state(self, modality: str, name: str) -> Any:
"""Return the current named input state for interactive applications."""
...

def begin_generation(self, generation: int) -> None:
"""Start a new output generation."""
...

def emit_chunk(self, result: StepResult) -> OutputDecision:
"""Deliver one generated step result."""
...

def should_exit(self) -> bool:
"""Return whether the surrounding run should stop."""
...

def close(self) -> Sequence[OutputArtifact]:
"""Finalize resources and return produced artifacts."""
...


@runtime_checkable
class FrameOutputSink(Protocol):
"""Narrow file/comparison tail used by higher-level output handlers."""

def handle_output(self, timestamp_s: float, chunk: StepResult) -> None:
"""Consume one timestamped generated chunk."""
...


@dataclass(slots=True)
class InferenceSessionApplicationAdapter:
"""Adapt an existing runtime session to ``ApplicationSession``."""

session: InferenceSession

def init(self) -> None:
init = getattr(self.session, "init", None)
if callable(init):
init()

def session_info(self) -> SessionInfo:
session_info = getattr(self.session, "session_info", None)
if not callable(session_info):
return SessionInfo()
value = session_info()
if not isinstance(value, SessionInfo):
raise TypeError(
"session.session_info() must return SessionInfo, "
f"got {type(value).__name__}."
)
return value

def next_step_requirements(self) -> StepRequirements | None:
next_requirements = getattr(self.session, "next_step_requirements", None)
if callable(next_requirements):
value = next_requirements()
if value is None or isinstance(value, StepRequirements):
return value
raise TypeError(
"session.next_step_requirements() must return StepRequirements "
f"or None, got {type(value).__name__}."
)

request = self.session.next_step_request()
if request is None:
return None
if not isinstance(request, StepRequest):
raise TypeError(
"session.next_step_request() must return StepRequest or None, "
f"got {type(request).__name__}."
)
return step_requirements_from_request(
request,
allow_user_input_window=True,
)

def step(self, model_input: InferenceInput) -> StepResult:
return self.session.step(model_input)

def reset(self, model_input: InferenceInput | None = None) -> None:
self.session.reset(model_input)

def close(self) -> None:
self.session.close()


@dataclass(slots=True)
class DemoAdapterApplication:
"""Adapt an existing ``DemoAdapter`` to the public ``Application`` shape."""

adapter: DemoAdapter
spec: DemoSpec
_scenario: PreparedScenario | None = field(default=None, init=False, repr=False)
_runtime: InferenceRuntime | None = field(default=None, init=False, repr=False)

def init(self, launch_args: Sequence[str]) -> None:
del launch_args
Comment thread
greptile-apps[bot] marked this conversation as resolved.
Outdated
config = _require_config(self.spec)
self.adapter.validate_config(config)
self._scenario = self.adapter.prepare_scenario(self.spec)

def create_session(self) -> ApplicationSession:
scenario = self._scenario
if scenario is None:
self.init(())
scenario = self._scenario
if scenario is None:
raise RuntimeError("DemoAdapterApplication failed to prepare a scenario.")
runtime = self.adapter.create_runtime(_require_config(self.spec))
self._runtime = runtime
Comment thread
greptile-apps[bot] marked this conversation as resolved.
Outdated
return InferenceSessionApplicationAdapter(
runtime.start_session(scenario.initial_inputs)
)

def close(self) -> None:
if self._runtime is not None:
self._runtime.close()
self._runtime = None


@dataclass(slots=True)
class RuntimeOutputSinkFrameAdapter:
"""Adapt a runtime ``OutputSink`` to the narrow frame-output tail."""

output_sink: OutputSink

def handle_output(self, timestamp_s: float, chunk: StepResult) -> None:
del timestamp_s
self.output_sink.write(chunk)


def _require_config(spec: DemoSpec) -> InferenceConfig:
config = spec.config
if config is None:
raise RuntimeError("DemoSpec.config must be populated before use.")
return config


IApplication = Application
IApplicationSession = ApplicationSession
IOutputSink = FrameOutputSink


__all__ = [
"Application",
"ApplicationSession",
"DemoAdapterApplication",
"FrameOutputSink",
"IApplication",
"IApplicationSession",
"IOutputSink",
"IOHandler",
"InferenceSessionApplicationAdapter",
"RuntimeOutputSinkFrameAdapter",
]
Loading
Loading