Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
f52e209
fix(ops): size persistent grids from the active device's SM count
igorls Aug 25, 2026
bf3fad9
feat(runtime): cross-request prefix seeding via a content-addressed s…
igorls Aug 25, 2026
6b5294b
fix(runtime): budget the seed-capture chunk split and skip trivial seeds
igorls Aug 25, 2026
9dda665
fix(serve): accept content parts in tool messages
igorls Aug 25, 2026
2605c5d
feat(serve): accept vLLM enable_thinking dialect
igorls Aug 25, 2026
352a49c
merge(serve): accept vLLM enable_thinking dialect (issue #2, upstream…
igorls Aug 25, 2026
74c52a8
perf(ops): prefetch next projection weights from moe d4 tail
ARVLab Aug 20, 2026
5064a2d
perf(ops): prefetch shared expert down weights behind moe router
ARVLab Aug 20, 2026
4570fde
perf(ops): fuse sigmoid gate into attention reduce epilogue
ARVLab Aug 20, 2026
375cff9
perf(ops): fuse q/k rmsnorm into one decode kernel
ARVLab Aug 20, 2026
4672e52
perf(ops): fold the moe router selection into the last D1 block
MichaelDementii Aug 20, 2026
b728ee7
docs: add decode micro-opt A/B GPU runbook
igorls Aug 25, 2026
3c66e2b
fix(serve): name the exception that terminates the process
igorls Aug 25, 2026
9b6ff3c
fix(serve): fail fast on warmup failure and clarify auto kv capacity …
igorls Aug 25, 2026
f6fbd86
feat(platform): native Windows (MSVC + CUDA) build for ninfer-serve
devan-carlin Aug 22, 2026
8f52f87
fix(platform): Windows vision build fixes (FFMPEG/curl + I/O)
devan-carlin Aug 24, 2026
6c10b7f
docs: add native Windows vs WSL2-tax A/B runbook
igorls Aug 25, 2026
b79b5d2
merge(platform): native Windows MSVC+CUDA build via upstream #84 (iss…
igorls Aug 25, 2026
31bf1b5
feat(serve): recover drifted Qwen tool calls with tolerant tool calli…
igorls Aug 25, 2026
c09eb18
feat(serve): reconcile content parts with allowed_types support
igorls Aug 25, 2026
adee82d
docs(serve): add live model runbook procedures for tool-calling robus…
igorls Aug 25, 2026
e2511e9
fix(ops): fence last-block MoE D1 score loads
igorls Aug 25, 2026
2ebef26
feat(serve): report prefix-cache hits in usage
igorls Aug 25, 2026
d3ee0d3
merge(serve): prefix-cache observability in usage + models context (i…
igorls Aug 25, 2026
326a5ff
fix(serve): add pre-listen boot watchdog and clean runbook
igorls Aug 25, 2026
ee6de59
merge(serve): fail fast on warmup failure + boot watchdog (issue #4, …
igorls Aug 25, 2026
811e7b5
fix(serve): keep the boot watchdog armed through exception unwind
igorls Aug 25, 2026
6aa77e9
fix(serve): faithfully adapt upstream #10 tolerant tool call parser a…
igorls Aug 25, 2026
ba72762
merge(serve): tool-call recovery (upstream #10) + content-parts recon…
igorls Aug 25, 2026
e6f15d1
docs(serve): drop stale near-miss wording from the parser header
igorls Aug 25, 2026
db7a122
merge(ops): decode micro-opts from upstream #69+#67, validated +4.4% …
igorls Aug 25, 2026
e6c261a
fix(runtime): include prefix-seed arena in device reservation
igorls Aug 25, 2026
72a274c
merge(runtime): include prefix-seed arena in device reservation (issu…
igorls Aug 25, 2026
c29e538
fix(serve): type tool-call args by schema and accept JSON payloads
igorls Aug 25, 2026
689b19d
feat(serve): add seed-store VRAM release, ranges, and admin control
igorls Aug 26, 2026
ac6e24d
fix(serve): gate /admin/vram behind --admin-vram and --api-key
igorls Aug 26, 2026
f1c708c
merge(serve): VRAM control surface, phase 1 (issue #7)
igorls Aug 26, 2026
efcce57
fix(engine): classify exceptions by type and recover on request-scope…
igorls Aug 26, 2026
322cabf
merge(engine): classify executor exceptions by type; recover request-…
igorls Aug 26, 2026
564a16c
fix(serve): suppress tool-call preamble at the caller, not the parser
igorls Aug 26, 2026
d463b76
merge(serve): tool-call argument handling — JSON payloads, schema typ…
igorls Aug 26, 2026
49e255f
docs(serve): correct parser contract comment after caller-side suppre…
igorls Aug 26, 2026
bad3a17
feat(supervisor): add native Windows process supervisor and dashboard
igorls Aug 26, 2026
4c5ab22
merge(supervisor): native Windows process supervisor + dashboard (iss…
igorls Aug 26, 2026
23a91ec
feat(docker): add a HEALTHCHECK so issue #10's 503 is observable
igorls Aug 26, 2026
6deb02b
feat(supervisor): CSRF/rebinding defenses, honest VRAM labels, monito…
igorls Aug 26, 2026
effe500
merge(supervisor): phase 2 P0+P1 — CSRF/rebinding fix, honest VRAM la…
igorls Aug 26, 2026
dd71512
feat(supervisor): give the tray a real icon that carries engine status
igorls Aug 26, 2026
94ed58a
fix(supervisor): read the request log's "event" key, not "type"
igorls Aug 26, 2026
f2891d5
feat(supervisor): raw 10 Hz VRAM/budget series, decoupled from nvidia…
igorls Aug 26, 2026
d4b88f3
wip(supervisor): issue #12 first cut - insights contract + first two …
igorls Aug 26, 2026
cd9aa9c
feat(supervisor): /api/insights - findings with evidence, for agents …
igorls Aug 26, 2026
87dc8b4
feat(supervisor): TTFT decomposition, and honest measured_over on una…
igorls Aug 26, 2026
c30251c
feat(supervisor): prefix-cache effectiveness insight
igorls Aug 26, 2026
870ab53
fix(serve): exit process on permanent executor failure and add real-p…
igorls Aug 26, 2026
ccd43cf
merge(runtime): exit the process on permanent executor failure (issue…
igorls Aug 26, 2026
e26bfe9
feat(supervisor): fire admin/vram markers on transition fields; flag …
igorls Aug 26, 2026
d8c726e
merge(supervisor): admin/vram event markers + pinned-tier insight
igorls Aug 26, 2026
24fe6e0
fix(supervisor): remove CUDA from the sampling path, persist the series
igorls Aug 26, 2026
d6a58ca
merge(supervisor): survive GPU device loss and persist the series
igorls Aug 26, 2026
1435913
fix(serve): recover parsed tool calls instead of discarding all on a …
igorls Aug 27, 2026
5bb8e81
merge(serve): partial tool-call recovery (issue #14)
igorls Aug 27, 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
71 changes: 66 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,28 @@ if(CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 13.1)
"${CMAKE_CUDA_COMPILER_VERSION}")
endif()

# CUDA 13's CCCL headers require MSVC's standard-conforming preprocessor.
if(MSVC)
add_compile_options($<$<COMPILE_LANGUAGE:CUDA>:-Xcompiler=/Zc:preprocessor>)
# windows.h defines max/min as macros that break std::max/std::min.
add_compile_definitions(NOMINMAX)
endif()

# Media (vision) decode and acquisition need FFMPEG and libcurl. Those are not
# part of the default Windows toolchain, so the text-only build
# (NINFER_BUILD_MEDIA=OFF) compiles API-compatible stubs instead and rejects
# vision requests at runtime.
if(WIN32)
set(NINFER_MEDIA_DEFAULT OFF)
else()
set(NINFER_MEDIA_DEFAULT ON)
endif()
option(NINFER_BUILD_MEDIA "Build FFMPEG/libcurl media decode and acquisition"
${NINFER_MEDIA_DEFAULT})

# ninfer_serve and prompt_input link ninfer_media_acquire unconditionally, so
# the target must exist whenever apps/tests build; NINFER_BUILD_MEDIA only
# selects the real (libcurl) vs stub implementation.
set(NINFER_BUILD_MEDIA_ACQUIRE OFF)
if(NINFER_BUILD_APPS OR BUILD_TESTING)
set(NINFER_BUILD_MEDIA_ACQUIRE ON)
Expand All @@ -55,11 +77,50 @@ if(NINFER_BUILD_APPS OR BUILD_TESTING)
endif()

find_package(CUDAToolkit REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(FFMPEG REQUIRED IMPORTED_TARGET
libavformat>=60 libavcodec>=60 libavutil>=58 libswscale>=7)
if(NINFER_BUILD_MEDIA_ACQUIRE)
pkg_check_modules(LIBCURL REQUIRED IMPORTED_TARGET libcurl>=7.85)
if(NINFER_BUILD_MEDIA)
if(WIN32)
# Windows: use find_path/find_library for FFMPEG + libcurl (no pkg-config)
set(FFMPEG_ROOT "${PROJECT_SOURCE_DIR}/../third_party/ffmpeg/ffmpeg-master-latest-win64-gpl-shared")
set(CURL_ROOT "${PROJECT_SOURCE_DIR}/../third_party/curl-inst")

find_path(FFMPEG_INCLUDE_DIR NAMES libavformat/avformat.h PATHS "${FFMPEG_ROOT}/include" NO_DEFAULT_PATH)
find_library(AVFORMAT_LIBRARY NAMES avformat.lib PATHS "${FFMPEG_ROOT}/lib" NO_DEFAULT_PATH)
find_library(AVCODEC_LIBRARY NAMES avcodec.lib PATHS "${FFMPEG_ROOT}/lib" NO_DEFAULT_PATH)
find_library(AVUTIL_LIBRARY NAMES avutil.lib PATHS "${FFMPEG_ROOT}/lib" NO_DEFAULT_PATH)
find_library(SWSCALE_LIBRARY NAMES swscale.lib PATHS "${FFMPEG_ROOT}/lib" NO_DEFAULT_PATH)

if(NOT FFMPEG_INCLUDE_DIR OR NOT AVFORMAT_LIBRARY OR NOT AVCODEC_LIBRARY OR NOT AVUTIL_LIBRARY OR NOT SWSCALE_LIBRARY)
message(FATAL_ERROR "FFMPEG libraries not found. Install BtbN ffmpeg-win64-gpl-shared into third_party/ffmpeg/")
endif()

add_library(PkgConfig::FFMPEG INTERFACE IMPORTED)
set_target_properties(PkgConfig::FFMPEG PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${FFMPEG_INCLUDE_DIR}"
INTERFACE_LINK_LIBRARIES "${AVFORMAT_LIBRARY};${AVCODEC_LIBRARY};${AVUTIL_LIBRARY};${SWSCALE_LIBRARY}"
)

if(NINFER_BUILD_MEDIA_ACQUIRE)
find_path(CURL_INCLUDE_DIR NAMES curl/curl.h PATHS "${CURL_ROOT}/include" NO_DEFAULT_PATH)
find_library(CURL_LIBRARY NAMES libcurl_imp.lib PATHS "${CURL_ROOT}/lib" NO_DEFAULT_PATH)

if(NOT CURL_INCLUDE_DIR OR NOT CURL_LIBRARY)
message(FATAL_ERROR "libcurl not found. Build curl with MSVC into third_party/curl-inst/")
endif()

add_library(PkgConfig::LIBCURL INTERFACE IMPORTED)
set_target_properties(PkgConfig::LIBCURL PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${CURL_INCLUDE_DIR}"
INTERFACE_LINK_LIBRARIES "${CURL_LIBRARY}"
)
endif()
else()
find_package(PkgConfig REQUIRED)
pkg_check_modules(FFMPEG REQUIRED IMPORTED_TARGET
libavformat>=60 libavcodec>=60 libavutil>=58 libswscale>=7)
if(NINFER_BUILD_MEDIA_ACQUIRE)
pkg_check_modules(LIBCURL REQUIRED IMPORTED_TARGET libcurl>=7.85)
endif()
endif()
endif()
find_package(Threads REQUIRED)

Expand Down
17 changes: 17 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ RUN apt-get update \
libswscale-dev \
ninja-build \
pkg-config \
python3 \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /src
Expand All @@ -31,6 +32,7 @@ ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get install --yes --no-install-recommends \
ca-certificates \
curl \
libavcodec60 \
libavformat60 \
libavutil58 \
Expand All @@ -45,4 +47,19 @@ WORKDIR /workspace
EXPOSE 8080
STOPSIGNAL SIGTERM

# /health is the only unauthenticated endpoint, so this needs no API key. It answers
# 503 once the inference executor has failed (issue #10) and 200 otherwise, which is
# what makes an alive-but-unusable server visible from outside the process.
#
# NINFER_PORT must match --port; HEALTHCHECK is static but the port is not. The
# server binds before loading the model and only listens afterwards, so expect
# connection-refused for the whole load — that is what start-period covers.
#
# NOTE: a restart policy does NOT act on health. Docker restarts on EXIT, not on
# unhealthy, so this makes the failed state observable and alertable; it does not
# by itself recover the container. Recovery needs a watcher (Swarm, an external
# monitor, or the native supervisor's health-restart path).
HEALTHCHECK --interval=30s --timeout=5s --start-period=180s --retries=3 \
CMD curl -fsS "http://127.0.0.1:${NINFER_PORT:-8080}/health" || exit 1

CMD ["ninfer-serve", "--help"]
Loading