diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ca5412e..3932af6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -80,6 +80,53 @@ jobs: with: targets: ${{ matrix.target }} + - name: Install nlprule tokenizer (Unix) + if: runner.os != 'Windows' + shell: bash + env: + TOKENIZER_URL: https://cuemap.dev/assets/en_tokenizer.bin.gz + TOKENIZER_SHA256: f54fd31ec463f8646d0239bb531a64e0210ed1ae02bf5e3b42aeeb9bff8305ba + run: | + curl -fsSL --retry 3 "${TOKENIZER_URL}" -o "${RUNNER_TEMP}/en_tokenizer.bin.gz" + echo "${TOKENIZER_SHA256} ${RUNNER_TEMP}/en_tokenizer.bin.gz" | sha256sum -c - + gzip -dc "${RUNNER_TEMP}/en_tokenizer.bin.gz" > "${RUNNER_TEMP}/en_tokenizer.bin" + echo "TOKENIZER_PATH=${RUNNER_TEMP}/en_tokenizer.bin" >> "${GITHUB_ENV}" + + - name: Install nlprule tokenizer (Windows) + if: runner.os == 'Windows' + shell: pwsh + env: + TOKENIZER_URL: https://cuemap.dev/assets/en_tokenizer.bin.gz + TOKENIZER_SHA256: f54fd31ec463f8646d0239bb531a64e0210ed1ae02bf5e3b42aeeb9bff8305ba + run: | + $archive = Join-Path $env:RUNNER_TEMP 'en_tokenizer.bin.gz' + $tokenizer = Join-Path $env:RUNNER_TEMP 'en_tokenizer.bin' + Invoke-WebRequest -Uri $env:TOKENIZER_URL -OutFile $archive + $actualHash = (Get-FileHash -Algorithm SHA256 -Path $archive).Hash.ToLowerInvariant() + if ($actualHash -ne $env:TOKENIZER_SHA256.ToLowerInvariant()) { + throw "Tokenizer checksum mismatch: expected $env:TOKENIZER_SHA256, got $actualHash" + } + $sourceStream = [System.IO.File]::OpenRead($archive) + $targetStream = [System.IO.File]::Create($tokenizer) + $gzipStream = [System.IO.Compression.GzipStream]::new( + $sourceStream, + [System.IO.Compression.CompressionMode]::Decompress + ) + try { + $gzipStream.CopyTo($targetStream) + } finally { + $gzipStream.Dispose() + $targetStream.Dispose() + $sourceStream.Dispose() + } + "TOKENIZER_PATH=$tokenizer" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + + - name: Use dynamic ONNX Runtime on Windows + if: runner.os == 'Windows' + shell: pwsh + run: | + "ORT_PREFER_DYNAMIC_LINK=1" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + - name: Test publication guards run: node --test scripts/publish-native-artifacts.test.cjs @@ -104,6 +151,11 @@ jobs: fi cp "target/${{ matrix.target }}/release/$native_binary" "$package_dir/bin/$packaged_binary" cp scripts/npm-native-wrapper.cjs "$package_dir/bin/cuemap" + if [[ "${{ matrix.npm_os }}" == "win32" ]]; then + runtime_dll="$(find "target/${{ matrix.target }}/release" -maxdepth 1 \( -type f -o -type l \) -iname 'onnxruntime*.dll' -print -quit)" + test -n "$runtime_dll" + cp "$runtime_dll" "$package_dir/bin/" + fi cp scripts/npm-native-README.md "$package_dir/README.md" cp LICENSE "$package_dir/LICENSE" cp NOTICE "$package_dir/NOTICE" diff --git a/src/main.rs b/src/main.rs index 19868d8..0a866c6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3597,25 +3597,21 @@ async fn handle_stop_at(pid_path: PathBuf) { #[cfg(unix)] { - use std::process::Command; if pid <= 1 || pid > i32::MAX as u32 { eprintln!("✗ Refusing to signal invalid server PID {}.", pid); return; } - let res = Command::new("kill") - .arg("-15") // SIGTERM - .arg(pid.to_string()) - .status(); - - match res { - Ok(s) if s.success() => { - println!("✓ Termination signal sent to server (PID: {})", pid); - let _ = std::fs::remove_file(pid_path); - } - _ => eprintln!( + // Call the platform API directly so minimal release containers do not + // need an external `kill` utility installed. + let result = unsafe { libc::kill(pid as libc::pid_t, libc::SIGTERM) }; + if result == 0 { + println!("✓ Termination signal sent to server (PID: {})", pid); + let _ = std::fs::remove_file(pid_path); + } else { + eprintln!( "✗ Failed to kill process {}. It might have already exited.", pid - ), + ); } }