Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
8c8020a
fix(tensorrt): TRT 10.16.1.11 + modelopt install + run_pip quote-fix
INTER-NYC Apr 23, 2026
4b23a56
chore(deps): add security floor pins for idna, Mako, urllib3
forkni May 24, 2026
d60be9a
fix(installer): install cuda-link 1.12.0 wheel + pywin32 311 + bump v…
forkni Jul 8, 2026
b1712e8
fix(installer): bump torch to 2.8.0+cu128 (matches repo's proven target)
forkni Jul 8, 2026
a61e225
fix(tensorrt): pin modelopt 0.43.0 + re-assert onnx 1.19.1 in FP8 block
forkni Jul 8, 2026
bb9c8d4
feat: auto-persist CUDALINK_LIB_PATH + bump cuda-link wheel to 1.12.1
forkni Jul 12, 2026
790ef42
fix: persist CUDALINK_DOORBELL=1 in phase4c for doorbell fast path
forkni Jul 13, 2026
06788dc
style: sort import blocks (ruff I001) in package __init__/__main__
forkni Jul 13, 2026
6b082dd
chore: add Claude Code automated PR review harness
forkni Jul 14, 2026
316d50b
chore: add Claude Code automated PR review harness
forkni Jul 14, 2026
8d538cf
feat: add install error-report generation (schema v1)
forkni Jul 14, 2026
eb35ff3
chore: raise review harness max-turns 60 -> 120
forkni Jul 14, 2026
d414d60
chore: raise review harness max-turns 60 -> 120
forkni Jul 14, 2026
587ac3e
fix: guard setx calls in phase4c_cuda_link_env against OSError
forkni Jul 14, 2026
a0e038c
Merge pull request #1 from forkni/deps/cuda-link-1.12-torch-modelopt-…
forkni Jul 14, 2026
a68aa8f
Merge pull request #2 from forkni/feat/installer-error-report
forkni Jul 14, 2026
9f38ea7
chore: bump install banner to v0.4.0
forkni Jul 14, 2026
2ea99e0
fix: consolidate TORCH_CUDNN_V8_API_ENABLED to single setx site in ph…
forkni Jul 14, 2026
3684426
feat: verify cuda-link + phase4c env vars + gap deps; add TensorRT st…
forkni Jul 15, 2026
1dd05e4
chore: retire inert TORCH_CUDNN_V8_API_ENABLED setx + verifier assert
forkni Jul 15, 2026
17445bd
fix: self-heal empty tensorrt_cu12 wrapper + retry flaky pip installs
forkni Jul 18, 2026
e1a9c92
fix: address CI review findings on tensorrt self-heal
forkni Jul 18, 2026
4647eba
Merge pull request #3 from forkni/fix/tensorrt-empty-wrapper-selfheal
forkni Jul 18, 2026
2edf5c5
Fix onnxruntime-gpu churn in TensorRT FP8 install step (#4)
forkni Jul 19, 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
39 changes: 39 additions & 0 deletions .github/instructions/python.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
applyTo: "**/*.py"
---

# Python review guidance — StreamDiffusion-installer (Windows CLI installer)

This is a Windows CLI (`sd-installer`) that drives a multi-phase install of CUDA/torch/ModelOpt/
ONNX/TensorRT dependencies by shelling out to `pip`, `nvidia-smi`, and related tools. There is no
ruff/pyrefly config in this repo (unlike the sibling `StreamDiffusion` library repo) — don't assume
its style conventions apply here.

## Flag these

- **`subprocess` calls with `shell=True`** where any part of the command is not a fixed literal —
string-built commands incorporating a version string, path, or other variable input are a command
injection risk. Prefer an argument list with `shell=False` (the existing pattern in
`sd_installer/report.py`'s `_nvidia_smi_driver()`).
- **Secret-shaped values leaking into logs or error reports.** `sd_installer/report.py` defines
`ENV_ALLOWLIST_PREFIXES` (`CUDALINK_`, `HF_`, `SD_`, `SDTD_`) and
`ENV_DENYLIST_SUBSTRINGS` (`TOKEN`, `KEY`, `SECRET`, `PASSWORD`, `PASSWD`, `CRED`) as the one
intentional pattern for env-var capture — new code that dumps environment/config state should
reuse or extend this, not add a parallel allowlist/denylist.
- **Install phases that leave the environment partially modified without being resumable or
clearly reported.** `installer.py`'s `install()` runs a `phases` list wrapped in try/finally —
a new phase should fail loudly (write an error report, re-raise) rather than silently continuing
past a failed step.
- **Error-reporting code that can raise.** `report.py` / `installer.py`'s
`_write_install_error_report()` must stay best-effort — any exception inside report generation
must be caught internally so it never masks or replaces the real installation error being
reported.
- **Windows-path assumptions that break on other separators/drives** — this installer targets
Windows specifically (see `pyproject.toml` classifiers), but avoid hardcoded backslash-joined
paths where `pathlib.Path` composition already works portably.

## Do NOT flag

- Missing type hints beyond what's already present — this repo doesn't enforce a strict typing
policy like the sibling library repo.
- Style nits (import order, line length) — there's no ruff/black config in this repo to violate.
47 changes: 47 additions & 0 deletions .github/workflows/claude-code-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Claude Code Review

on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
# base-branch filter: PRs *into* main, or into the deps stack that
# feat/installer-error-report chains on, so Claude fires on both stacked PRs.
branches: [main, deps/cuda-link-1.12-torch-modelopt-onnx]

jobs:
review:
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: write
id-token: write
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }

- uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
track_progress: true # forces tag mode -> sticky comment updates in place
use_sticky_comment: true # one review comment across pushes, not a new one each time
show_full_output: true # surfaces full tool output/denials in the run log for debugging
plugin_marketplaces: "https://github.com/anthropics/claude-code.git"
plugins: "code-review@claude-code-plugins"
prompt: "/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}"
claude_args: >-
--max-turns 120
--allowedTools "Bash(git diff:*),Bash(git status:*),Bash(git log:*),Bash(git fetch:*),Bash(git merge-base:*),Bash(git rev-parse:*),Bash(git remote:*),Bash(git branch:*),Bash(git show:*),Bash(echo:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh release view:*),Bash(python:*),Bash(python3:*),Bash(pytest:*),Skill,Write(/tmp/*)"
--append-system-prompt "Repo-specific focus: this is a Windows CLI installer that shells out to
pip/nvidia-smi/conda and drives multi-phase installs (cuda-link, torch, modelopt, onnx, tensorrt).
Flag subprocess calls that are shell=True with unsanitized/user-influenced input, install phases
that leave the environment partially-modified on failure without a clear rollback or resumable
state, and any place a secret-shaped env var (TOKEN/KEY/SECRET/PASSWORD/CRED) could leak into a
log or error report -- see sd_installer/report.py's ENV_ALLOWLIST_PREFIXES/ENV_DENYLIST_SUBSTRINGS
pattern, which is the intentional convention to follow, not duplicate ad hoc. Error-reporting code
(report.py, installer.py's _write_install_error_report) must stay best-effort: it must never raise
past its own try/except, since a reporting bug must not mask the real install failure. Skip generic
style nits.
Tool usage: never run filesystem-wide search (find /, grep -r /), stay inside the repo checkout.
Never redirect Bash output to a file with > or >>, it is blocked; pipe to head/tail or just read
the direct stdout instead."
92 changes: 76 additions & 16 deletions sd_installer/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@
python -m sd_installer install --cuda cu128 # Install with specific CUDA
python -m sd_installer verify # Verify existing installation
python -m sd_installer diagnose # Detailed diagnostics
python -m sd_installer report # Write a diagnostic report on demand
python -m sd_installer repair # Auto-fix known issues
python -m sd_installer generate-bat # Generate standalone batch file
python -m sd_installer install-tensorrt # Install TensorRT packages
"""

import argparse
import os
import sys
from pathlib import Path


def find_base_folder() -> Path:
"""
r"""
Find the StreamDiffusion base folder (where setup.py lives).

Runtime structure:
Expand All @@ -47,9 +47,9 @@ def find_base_folder() -> Path:
# __file__ = .../StreamDiffusion-installer/sd_installer/cli.py
# We want: .../StreamDiffusion/
this_file = Path(__file__).resolve()
sd_installer_pkg = this_file.parent # sd_installer/
installer_repo = sd_installer_pkg.parent # StreamDiffusion-installer/
base = installer_repo.parent # StreamDiffusion/
sd_installer_pkg = this_file.parent # sd_installer/
installer_repo = sd_installer_pkg.parent # StreamDiffusion-installer/
base = installer_repo.parent # StreamDiffusion/
if (base / "setup.py").exists():
return base

Expand Down Expand Up @@ -85,7 +85,7 @@ def cmd_check(args):
if venv_path.exists():
print(f"Venv: Found at {venv_path}")
else:
print(f"Venv: Not found (will be created during install)")
print("Venv: Not found (will be created during install)")

# Check StreamDiffusion setup.py (base folder IS StreamDiffusion)
setup_py = base / "setup.py"
Expand Down Expand Up @@ -197,15 +197,59 @@ def cmd_diagnose(args):
print(f" [{status}] {check['name']}")
if check["error"]:
# Print just the last line of the error
error_line = check["error"].split('\n')[-1][:60]
error_line = check["error"].split("\n")[-1][:60]
print(f" {error_line}")

return 0


def cmd_report(args):
"""Generate a diagnostic report on demand (no failure required)."""
from .report import write_error_report

try:
base = Path(args.base_folder) if args.base_folder else find_base_folder()
except RuntimeError as e:
print(f"ERROR: {e}")
return 1

# Find Python executable in venv
venv_path = base / "venv"
if sys.platform == "win32":
python_exe = venv_path / "Scripts" / "python.exe"
else:
python_exe = venv_path / "bin" / "python"

if not python_exe.exists():
print(f"ERROR: Virtual environment not found at {venv_path}")
return 1

print("Generating StreamDiffusionTD Diagnostic Report")
print("=" * 40)

out_dir = Path(args.output) if args.output else base / "error_reports"
report_path = write_error_report(
out_dir,
{
"stage": "installation",
"phase": "manual",
"python_exe": str(python_exe),
"base_folder": str(base),
"venv_path": str(venv_path),
},
)

if report_path:
print(f"\nReport written to: {report_path}")
return 0

print("ERROR: Failed to write report.")
return 1


def cmd_repair(args):
"""Auto-fix known issues."""
from .verifier import Verifier, KNOWN_ERRORS
from .verifier import Verifier

try:
base = Path(args.base_folder) if args.base_folder else find_base_folder()
Expand Down Expand Up @@ -236,6 +280,7 @@ def cmd_repair(args):
for check in info["checks"]:
if not check["passed"] and check["error"]:
from .verifier import match_known_error

fix = match_known_error(check["error"])
if fix:
fixes_needed.append((check["name"], fix))
Expand All @@ -245,10 +290,15 @@ def cmd_repair(args):
# numpy 2.x
numpy_ver = info["versions"].get("numpy", "")
if numpy_ver.startswith("2."):
fixes_needed.append(("numpy version", {
"cause": f"numpy {numpy_ver} detected (2.x breaks things)",
"fix": "pip install numpy==1.26.4 --force-reinstall"
}))
fixes_needed.append(
(
"numpy version",
{
"cause": f"numpy {numpy_ver} detected (2.x breaks things)",
"fix": "pip install numpy==1.26.4 --force-reinstall",
},
)
)

if not fixes_needed:
print("No known issues detected that can be auto-fixed.")
Expand All @@ -264,18 +314,19 @@ def cmd_repair(args):

if not args.yes:
response = input("Apply fixes? [y/N]: ")
if response.lower() != 'y':
if response.lower() != "y":
print("Aborted.")
return 0

# Apply fixes
import subprocess

for name, fix in fixes_needed:
print(f"Applying fix for {name}...")
cmd = [str(python_exe), "-m", "pip"] + fix["fix"].replace("pip ", "").split()
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode == 0:
print(f" OK")
print(" OK")
else:
print(f" FAILED: {result.stderr}")

Expand Down Expand Up @@ -314,7 +365,7 @@ def cmd_generate_bat(args):

def cmd_install_tensorrt(args):
"""Install TensorRT packages."""
from .tensorrt import install, get_cuda_version_from_torch
from .tensorrt import get_cuda_version_from_torch, install

print("StreamDiffusionTD TensorRT Installation")
print("=" * 40)
Expand Down Expand Up @@ -378,10 +429,19 @@ def main():
diagnose_parser = subparsers.add_parser("diagnose", help="Run detailed diagnostics")
diagnose_parser.set_defaults(func=cmd_diagnose)

# report command
report_parser = subparsers.add_parser("report", help="Generate a diagnostic report on demand")
report_parser.add_argument(
"--output",
help="Directory to write the report into (default: base folder/error_reports)",
)
report_parser.set_defaults(func=cmd_report)

# repair command
repair_parser = subparsers.add_parser("repair", help="Auto-fix known issues")
repair_parser.add_argument(
"-y", "--yes",
"-y",
"--yes",
action="store_true",
help="Apply fixes without prompting",
)
Expand Down
Loading