Port Windows installer/ncp fixes and a real nomic-embed-text default

- install-windows.ps1: warn about a leftover profile-based ncp() that
  would shadow ncp.cmd; the "press any key to close" footer now skips
  the wait when stdin is redirected (was hanging indefinitely) and
  exits cleanly instead of Stop-Process when it owns the window; pulls
  nomic-embed-text alongside the chat/memory models.
- management/ncp.py: ncp start / start -b bring Ollama up automatically;
  longer timeout + real error message on a slow model warm.
- synapse/nexus_config.py: DEFAULT_EMBED_MODEL, single source of truth
  alongside DEFAULT_CHAT_MODEL/DEFAULT_MEMORY_MODEL.
- synapse/ollama_manager.py: is_available() cached instead of spawning a
  process per /status poll; is_running() timeout dropped 2s -> 0.5s so a
  healthy backend stops reading as dead; embed() reads the new default
  instead of a hardcoded string; de-duplicated serve-env setup.

Ported via bin/publish.sh from NexusOS-jon.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-22 22:05:37 -05:00
co-authored by Claude Sonnet 5
parent 4a13767ffc
commit ec8f2e08f6
5 changed files with 120 additions and 50 deletions
+61 -15
View File
@@ -178,6 +178,30 @@ try {
Write-Warn " $RepoRoot\management"
}
# -- Legacy profile shim check --------------------------------------------------
# An earlier version of this installer registered ncp as a `function ncp` in the
# PowerShell profile instead of management\ncp.cmd (see the "why" above). Profile
# functions resolve before PATH executables, so a leftover one silently shadows
# the real ncp.cmd - `ncp` still runs, just the wrong code, with no error. We do
# not rewrite the user's profile automatically: it is their file, and a blind
# strip risks mangling whatever else lives in it alongside it. Just flag it.
Write-Step "Checking for a stale ncp() in your PowerShell profile"
$DocsRoot = [Environment]::GetFolderPath("MyDocuments")
$ProfileCandidates = @(
(Join-Path $DocsRoot "WindowsPowerShell\Microsoft.PowerShell_profile.ps1"),
(Join-Path $DocsRoot "PowerShell\Microsoft.PowerShell_profile.ps1")
)
$Shadowed = $ProfileCandidates | Where-Object {
(Test-Path $_) -and (Select-String -Path $_ -Pattern '^\s*function\s+ncp\b' -Quiet)
}
if ($Shadowed) {
Write-Warn "Found an old 'function ncp' that will shadow the real ncp.cmd:"
foreach ($p in $Shadowed) { Write-Warn " $p" }
Write-Warn " Remove that function from the file(s) above so ncp resolves to ncp.cmd."
} else {
Write-OK "No stale ncp() in your PowerShell profile"
}
# -- Desktop shortcut ----------------------------------------------------------
Write-Step "Creating desktop shortcut"
try {
@@ -211,10 +235,11 @@ try {
# Read them instead of hardcoding, so the installer can never pull one model
# while the backend defaults to another.
Push-Location $RepoRoot
$ChatModel = (& $VenvPy -c "from synapse.nexus_config import DEFAULT_CHAT_MODEL as m; print(m)")
$MemModel = (& $VenvPy -c "from synapse.nexus_config import DEFAULT_MEMORY_MODEL as m; print(m)")
$ChatModel = (& $VenvPy -c "from synapse.nexus_config import DEFAULT_CHAT_MODEL as m; print(m)")
$MemModel = (& $VenvPy -c "from synapse.nexus_config import DEFAULT_MEMORY_MODEL as m; print(m)")
$EmbedModel = (& $VenvPy -c "from synapse.nexus_config import DEFAULT_EMBED_MODEL as m; print(m)")
Pop-Location
if ($LASTEXITCODE -ne 0 -or -not $ChatModel -or -not $MemModel) {
if ($LASTEXITCODE -ne 0 -or -not $ChatModel -or -not $MemModel -or -not $EmbedModel) {
Write-Fail "Could not read the default models from synapse\nexus_config.py - the venv install is broken"
}
@@ -255,7 +280,7 @@ Pop-Location
if ($seedOk) { Write-OK "Default model set to $ChatModel" }
else { Write-Warn "Could not persist default model - pick it at the top of the chat instead." }
Write-Step "Pulling models ($ChatModel for chat, $MemModel for memory)"
Write-Step "Pulling models ($ChatModel for chat, $MemModel for memory, $EmbedModel for recall)"
# A prompt, not "press Ctrl+C to skip": Ctrl+C in PowerShell 5.1 terminates the
# whole script, so the escape hatch the installer advertised was also the one
# thing that stopped it finishing - no Ollama cleanup, no summary, no window
@@ -277,6 +302,10 @@ if ($pullAnswer -match '^\s*(n|no)\s*$') {
ollama pull $MemModel
if ($LASTEXITCODE -eq 0) { Write-OK "$MemModel ready (memory curator)" }
else { Write-Warn "$MemModel pull skipped/failed - the memory service will fall back to the chat model." }
ollama pull $EmbedModel
if ($LASTEXITCODE -eq 0) { Write-OK "$EmbedModel ready (conversation recall)" }
else { Write-Warn "$EmbedModel pull skipped/failed - recall will fall back to lexical search." }
}
# -- Make Ollama manual-start (NexusOS owns the lifecycle) ----------------------
@@ -326,15 +355,32 @@ Write-Host " A process reads PATH once, when it starts. This shell started befo
Write-Host " the installer put management\ on PATH, so it will never see ncp no" -ForegroundColor DarkGray
Write-Host " matter what you run here. The next terminal you open will." -ForegroundColor DarkGray
Write-Host ""
Read-Host " Press Enter to close this window"
# Stop-Process on our own PID, not `exit`: `exit` only ends the window when the
# host was started with -File. Run interactively - `& .\install-windows.ps1` from
# a shell already open, which is the common case - it would just return to the
# prompt in a session whose PATH is permanently stale. Killing the host closes
# the window either way, which is the point: the user cannot accidentally keep
# using a shell where ncp will never resolve.
# Caveat: a Start-Transcript in this window never reaches Stop-Transcript. The
# transcript is flushed as it is written, so the content survives without the
# closing footer.
Stop-Process -Id $PID
# Skip the wait entirely when stdin is redirected: nobody is at the keyboard to
# press anything, and both ReadKey and Read-Host were confirmed (empirically,
# not just in theory) to hang indefinitely in that case instead of failing
# fast - Read-Host only fails fast under an explicit -NonInteractive flag,
# which is not how the self-elevation Start-Process above launches this script.
if (-not [Console]::IsInputRedirected) {
Write-Host " Press any key to close this window..." -ForegroundColor Yellow
try { $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") } catch { Read-Host | Out-Null }
}
# $OwnsWindow means this is the elevated instance the self-elevation block above
# launched with `-File`, so a clean `exit` closes it - and does so with exit code
# 0, which is what lets Windows Terminal's closeOnExit actually close the tab
# instead of treating an abrupt kill as a crash and falling back to a fresh
# shell in the pane. Without $OwnsWindow we are in a shell the user already had
# open (they ran an admin PowerShell and invoked the script directly, so it was
# never re-launched with -File) - `exit` there would just return to the prompt
# in a session whose PATH is permanently stale, so kill the host instead; the
# point is the user cannot accidentally keep using a shell where ncp never
# resolves.
# Caveat: a Start-Transcript in this window never reaches Stop-Transcript in the
# Stop-Process path. The transcript is flushed as it is written, so the content
# survives without the closing footer.
if ($OwnsWindow) {
exit 0
} else {
Stop-Process -Id $PID
}