Repository navigation
feat: add native Windows support (server + windows/amd64 llama-cpp backend) - #11429
LionelColaso wants to merge 1 commit into
Conversation
6caf372 to
b347f46
Compare
b347f46 to
c16c463
Compare
b6bbe35 to
4e16c60
Compare
localai-org-maint-bot
left a comment
There was a problem hiding this comment.
@mudler the Windows launcher concerns are resolved on the rebased head: the unused run.cmd is removed, the native run.exe path is now explained, and backends/llama-cpp-windows is serialized in .NOTPARALLEL. I reviewed the range-diff from the prior head; git diff --check, the launcher build, pkg/system, and all 48 backend-filter tests pass. Good from my side once the newly restarted Windows/backend CI completes.
319917b to
b269dde
Compare
|
@mudler the requested launcher change is addressed on the rebased head: the compiled |
b269dde to
7705d38
Compare
e9f247d to
547ff9d
Compare
9c1fe20 to
788603f
Compare
e353b89 to
c334688
Compare
c334688 to
4c2f267
Compare
localai-org-maint-bot
left a comment
There was a problem hiding this comment.
Found a runtime blocker: pkg/model/process.go sets process.WithName("powershell.exe") (a bare filename) together with process.WithWorkDir(workDir). On Windows, Go's syscall.StartProcess resolves the application name relative to attr.Dir when both are set — so it looks for <workDir>\powershell.exe instead of searching PATH, and CreateProcess with an explicit lpApplicationName does no PATH lookup. Every Windows backend launch will fail with ERROR_FILE_NOT_FOUND.
Fix: resolve the full path before calling WithName, e.g. exec.LookPath("powershell.exe") (which searches PATH and finds System32), or hardcode C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe.
The rest of the PR looks sound — capability detection ordering, docs, CI workflows. Once this is fixed, it should be good to merge.
4c2f267 to
bd37efd
Compare
bd37efd to
78bcf2d
Compare
mudler
left a comment
There was a problem hiding this comment.
we are almost there :) thanks for the patience @LionelColaso. Last review pass and then should be good to go
7bc3106 to
12cbf4e
Compare
mudler-agent
left a comment
There was a problem hiding this comment.
Two findings from the Windows support review. Rechecked against the current head; the affected code is unchanged.
eb12e3d to
b548d4f
Compare
I use it and tested it both (local-ai.exe and llama-cpp backend) everything seems to be working and been using it. |
No problem I understand its not easy it was good experience and thanks for having patience as well now everything should be working as per my local testing Hopefully all well now Thanks
|
b548d4f to
a26e58f
Compare
1eebcce to
be45e6b
Compare
be45e6b to
bb25152
Compare
|
Thanks for the work on this. It needs a rebase because it conflicts with master. Two items from the earlier automated review that I could not confirm are fixed on the current head, could you check both?
|
|
Thanks for continuing to work on this! I reviewed the current head,
Validation: all 51 backend-filter tests, |
|
I need to add some fixes for issue related to addons which causes build to fail on current updated source so till then its not merge ready |
…kend)
Build and packaging:
- Native windows/amd64 backend builds under MSYS2 (no WSL, no Docker):
Makefile targets, scripts/build/llama-cpp-windows.{sh,ps1}, CI matrix
includeWindows consumed by a new backend-jobs-windows workflow.
- local-ai.exe builds with CGO_ENABLED=0 while Windows backend builds use
full mingw gcc/CGO; document both in .agents/windows-backends.md, which
also covers all 9 steps to add a Windows backend (Makefile target, build
script, PS1 entry point, CI matrix entry, gallery entries, capability
preference rules, launcher, process tree cleanup, testing).
Add-on subsystem portability:
- Replace direct syscall usage in hostsettings, policy, hostgrants,
artifacts, resources/selection, ownership, recovery/backup, and the
studio sandbox host with per-platform files (store_unix.go /
store_windows.go). Windows file locks use LockFileEx instead of
process-local locks.
- Deduplicate Windows directory-sync tolerance into
pkg/atomicfile.SyncDirTolerant, shared by journal.go, artifacts/store.go,
resources/selection.go, jsonstore/store.go, blob/fs.go, and
hostgrants/store.go. On Windows syncing a directory handle fails with
"Access is denied" (ERROR_ACCESS_DENIED, matched via errors.Is); the
file data is already synced so treat that as non-fatal. Without this
every host-grants write fails on Windows.
- Default the add-on host operation policy to a grant-all floor on Windows
when no --addon-host-policy/--addon-host-ops is provided, so first-run
end users do not hit permission errors. The deployment-wide floor is the
"*" key of the grant map; the grant side of both hostops.staticAuthority
and the hostgrants Floor now consults it (the deny side already did), so
admission, the Apps listing and the supervisor endpoint decision all see
the Windows default through the normal authority chain.
- Treat "*" in host-op grants as a wildcard operation in the broker.
Backend process launch:
- Refactor pkg/model process launch behind a processLauncher interface so
process.go has no runtime.GOOS branch: processLauncherWindows (Windows:
start via exec.Cmd, assign the job tree immediately after CreateProcess
returns, before the launcher can spawn children) and processLauncherOther
(Run() then trackProcessTree).
- resolveLauncher on Windows launches llama-cpp-grpc.exe directly when the
backend ships it, falls back to run.ps1/run.sh via PowerShell, and as a
last resort resolves the raw gallery contract path against workDir
(CreateProcess does not search the child's working directory). Do not
set LLAMACPP_GRPC_SERVERS to select the grpc binary: grpc-server.cpp
also reads that variable as RPC server addresses (add_rpc_devices), so
setting it to "1" makes the backend try to connect to endpoint "1" and
crash during model load.
- startProcessWindows converts "--addr <addr>" to "--addr=<addr>", adds
the backend's lib/ directory to the front of PATH (joined with the path
list separator, replacing the existing entry) so DLLs are found, and
writes the pidfile so IsAlive/Stop keep working.
- deleteProcess on Windows terminates the job tree directly instead of
go-processmanager's Stop(), whose Signal(0)-based liveness check hangs
up to 15s on Windows.
- Unit tests for resolveLauncher (grpc.exe preferred, run.ps1 fallback,
raw path) and the Windows process tree.
Gallery:
- windows-llama-cpp entries in the backend library (latest + master
channels). The release entry is mutable until backend-jobs-windows
pushes the image once; pin it with backendcatalog --repin afterwards.
backend/index.yaml is the generated output of the library.
Also fixes found in cross-platform review: unused imports and a
nonexistent os.Root.ReadDir call in the unix files, freeBytes on Windows
now queries GetDiskFreeSpaceEx instead of returning a constant, POSIX
permission and symlink test assertions are skipped where Windows cannot
express them, and Plan.md is dropped (the durable guide is
.agents/windows-backends.md).
Signed-off-by: Lionel Colaso <lionelcolaso@outlook.com>

Adds native Windows support end to end: LocalAI now releases a
windows/amd64server binary, and thellama-cppbackend is built natively forwindows/amd64under MSYS2 UCRT64 and packaged as an OCI image tar that LocalAI installs and runs as a native process - no docker daemon or WSL required on the host.Server side
goreleaser: add
windows(amd64/arm64) to the release targetsMakefile: download the win64
protoczip and renameprotoc.exetoprotoc, resolve code-gen plugins via--plugininstead ofPATH, forceSHELL=shand name the binarylocal-ai.exeon Windows, ignoreprotoc.exebuild-test.yaml: add a native
windows-latestbuild gate that installs GNU make via Chocolatey, adds Git for Windows'usr/bintoPATHand builds withCGO_ENABLED=0pkg/downloader: close the write handle before removing or renaming a partial download so Windows file locks do not break the resume and error paths; guard the POSIX-permission and symlink tests on non-Windows
tests: Windows guards and path fixes for
core/gallery,video_internal,loaderand the testcontainers database setupBackend side
scripts/build/llama-cpp-windows.sh: builds gRPC from source (pinned v1.59.0, with mingw-w64 fixes for c-ares, boringssl and zlib), then the three llama.cpp variants (cpu-all with
GGML_CPU_ALL_VARIANTS+ Vulkan, rpc, and the AVX-off fallback), bundles the mingw runtime DLLs and ships an OCI tar vialocal-ai util create-oci-image. Re-runnable and auto-dispatches into MSYS2 when launched from Git for Windows' bash.JOBSoverride supported for memory-limited hosts.core/gallery:
backends installskips the OCI-registry digest lookup forocifile://streams (a local tarball is not a registry reference), so the local-build install step no longer prints a confusingcould not parse referencedigest warningbackend/cpp/llama-cpp/run.ps1: PowerShell launcher (mirrors
run.sh) thatpkg/model/process.gostarts on Windowsbackend/index.yaml:
windows/amd64backend entry and variantspkg/system/capabilities.go: windows engine preference rules so the gallery picks the native build on Windows hosts
.github/backend-matrix.yml + backend_build_windows.yml: windows matrix entries and a reusable windows build workflow;
backend.ymlandbackend_pr.ymlwire the windows backend jobs (build on PR, publish on master)docs/content/getting-started/windows.md plus related page updates (GPU-acceleration, install)
Notes for Reviewers
All 5 review items from mudler-agent's Oct 27 review are resolved:
path/filepathimport instore_unix.go— addedwindows-llama-cppandwindows-llama-cpp-developmententries togallery/backends/index.yamlLockFileExOS-backed locks inpolicy,artifacts,ownership, andselectionstoresprocessLauncherinterface; Windows usesCREATE_SUSPENDED→ assign job tree →ResumeThread, so children can't escape before assignmentAdditional fixes:
blob.goandfs.gonow tolerate Windows "Access is denied" whenos.Renametargets an existing filepkg/atomicfile.SyncDirTolerant()shared byjournal.go,artifacts/store.go,resources/selection.go,jsonstore/store.go,blob/fs.goprocessLauncherWindows/processLauncherOther;process.gohas noruntime.GOOSbranchprocess_launcher_windows_test.go,process_launcher_other_test.go.agents/windows-backends.mdcovering all 9 steps to add a Windows backendtests/addons/foundation/cluster/*.go//go:build !windows//→ proper newlineThe Windows backend image ships three llama-cpp executables picked by the
run.ps1launcher:llama-cpp-cpu-all.exe(all ggml CPU variants, auto-detects a Vulkan device at runtime and falls back to CPU),llama-cpp-grpc.exe(gRPC-RPC build, selected whenLLAMACPP_GRPC_SERVERSis set) andllama-cpp-fallback.exe(static, AVX-off fallback). The mingw runtime DLLs are bundled in the image, so no MSYS2 install is needed on the host.macOS is intentionally unaffected; the Darwin matrix entries are unchanged.
Review follow-ups (richiejp): backend processes now run inside a Windows Job Object with
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE(pkg/model/windows_job_windows.go), so model unloads, graceful shutdown, and an abrupt local-ai.exe exit all reap the wrapper + backend tree; it degrades to a logged warning when the host already nests the process in a non-breakaway job.Windows smoke suite (
tests/e2e/windows): builds and boots the real local-ai.exe with the mock-backend laid out exactly as a gallery install ships it (run.shfor discovery,run.ps1to launch) and asserts a chat completion via run.ps1 plus job-object tree reaping after hard-killing local-ai.exe. Self-skips on non-Windows hosts; wired asmake test-windows-smokeand awindows-latestjob intests-e2e.yml. 2/2 specs pass locally on a Windows host and on thetests-windows-smokeCI job.backend_build_windows.yml's publish job now signs the windows images keyless with cosign (same flow asbackend_merge.yml); the galleryverification:block stays unpopulated until it can cover every published variant.Commits are DCO-signed and carry an
Assisted-by:trailer per .agents/ai-coding-assistants.md.Signed commits
Yes, I signed my commits.
Documentation updated (docs/content/) for user-facing changes, or not applicable
Closes #2368