Skip to content

Fix #2213: Bug: admin/restart is self-destructive on Windows (pkill/bash/tsx unavailable, d - #2214

Closed
Memtensor-AI wants to merge 4 commits into
MemTensor:dev-v2.0.29from
Memtensor-AI:bugfix/autodev-2213-20260805050240965
Closed

Fix #2213: Bug: admin/restart is self-destructive on Windows (pkill/bash/tsx unavailable, d#2214
Memtensor-AI wants to merge 4 commits into
MemTensor:dev-v2.0.29from
Memtensor-AI:bugfix/autodev-2213-20260805050240965

Conversation

@Memtensor-AI

Copy link
Copy Markdown
Collaborator

Description

Fixed #2213: POST /api/v1/admin/restart (and the same code path in /api/v1/admin/clear-data) no longer self-destructs the Memory Viewer daemon on Windows. On Windows portable installs the historical pkill + bash -c "... tsx bridge.cts --daemon" sequence silently failed while the follow-up SIGTERM-self-kill always succeeded, so the daemon died with no replacement — a fault that also triggered on every "Save settings" click because SettingsView.tsx posts to /admin/restart after each save.

The fix adds an isWindowsPlatform() guard in apps/memos-local-plugin/server/routes/admin.ts (with a new ServerOptions.platform seam so tests inject the platform cleanly). When the runtime is Windows AND no supervisor is detected (INVOCATION_ID / XPC_SERVICE_NAME absent), we now skip the pkill+bash+shutdown chain, keep the daemon alive, and return { ok: false, restarting: false, manualRestartRequired: true, message: ... } for /admin/restart; /admin/clear-data still tears down MemoryCore and unlinks the DB / WAL / SHM / bridge-status files but returns restarting: false, manualRestartRequired: true and lets the user restart Hermes themselves. Supervised Windows hosts keep the original self-shutdown path so a supervisor can respawn the daemon.

Viewer client updates: viewer/src/stores/restart.ts::triggerRestart() recognises the new payload and enters a new manualRestartRequired phase (instead of endlessly polling a healthy server), and RestartOverlay.tsx renders the phase with the same terminal treatment as restartFailed. Bilingual copy added under restart.manualRequired / restart.manualRequiredHint in viewer/src/stores/i18n.ts.

Verified: tests/unit/server/admin.test.ts — 7/7 green (3 new Windows-specific tests + 4 preserved). Broader tests/unit/server/ tests/unit/config/ — 137 passing, 1 pre-existing failure in http.test.ts::POST /migrate/openclaw/run that reproduces on the untouched base commit (confirmed via git-stash sandwich). Both tsc -p tsconfig.json and tsc -p tsconfig.viewer.json complete with no errors. cc @whipser030 @hijzy

Related Issue (Required): Fixes #2213

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor (does not change functionality, e.g. code style improvements, linting)
  • Documentation update

How Has This Been Tested?

Automated tests are pending.

  • Unit Test
  • Test Script Or Test Steps (please provide)
  • Pipeline Automated API Test (please provide)

Checklist

  • I have performed a self-review of my own code
  • I have commented my code in hard-to-understand areas
  • I have added tests that prove my fix is effective or that my feature works
  • I have created related documentation issue/PR in MemOS-Docs (if applicable)
  • I have linked the issue to this PR (if applicable)
  • I have mentioned the person who will review this PR

@whipser030, @hijzy please review this PR.

Reviewer Checklist

…emTensor#2213)

`POST /api/v1/admin/restart` used to run `pkill` + `bash -c "... tsx bridge.cts --daemon"`
and then `SIGTERM` its own PID after 200 ms. On Windows the first two calls
are silent no-ops (pkill/bash unavailable), but the self-shutdown always
succeeds, so the Memory Viewer daemon died with nothing to respawn it —
including on every "Save settings" click, since SettingsView triggers the
restart overlay after save.

Guard the Hermes restart and clear-data flows with a new
`isWindowsPlatform()` check + `ServerOptions.platform` seam. When the
runtime is Windows and no supervisor (launchd / systemd / NSSM-style
INVOCATION_ID) is detected, we now:

* skip the pkill+bash+shutdown sequence,
* keep the daemon alive,
* return `{ ok: false, restarting: false, manualRestartRequired: true, message: ... }`
  from /admin/restart, and
* still wipe the DB / WAL / SHM / bridge-status files from /admin/clear-data
  but return `restarting: false, manualRestartRequired: true` afterwards.

Supervised Windows hosts keep the original self-shutdown path so the
supervisor can respawn the process.

Viewer `stores/restart.ts` recognises the new payload and enters a new
`manualRestartRequired` phase (EN + 中文 copy), and `RestartOverlay`
renders it with the same terminal treatment as `restartFailed`.
@Memtensor-AI Memtensor-AI added ai:generated Generated or modified by AI | 由 AI 生成或修改 area:plugin OpenClaw & Hermes status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 labels Aug 5, 2026
@Memtensor-AI

Memtensor-AI commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator Author

🤖 Open Code Review

Target: PR #2214
Task: dbbd8654162c0789
Base: dev-v2.0.29
Head: bugfix/autodev-2213-20260805050240965
Head SHA: 52d349957c426b00dfe5e6256d953d3901b2f343

OpenCodeReview: No comments generated. Looks good to me.

Generated by cloud-assistant via Open Code Review.

@Memtensor-AI

Copy link
Copy Markdown
Collaborator Author

🔧 Open Code Review requested Agent fix

Open Code Review found 8 issue(s). I have resumed the development Agent to fix them.

  • Task: dbbd8654162c0789
  • Fix attempt: 1/2
  • Finding delta: 0 repeated / 8 new / 0 likely resolved

The Agent will push a new commit to this PR branch. OCR will recheck after the commit is pushed.

- Return ok:true on the restart route's Windows manual path so the
  contract matches clear-data; typed SDK wrappers that read `ok` as a
  success discriminant no longer misclassify the intentional decline.
- Report the resolved `platform` variable in both Windows manual
  responses instead of hardcoding `"win32"`, so tests that inject
  `lifecycle.platform` see the value they set.
- Hoist `agent`/`supervised`/`platform` to the top of the restart
  handler, mirroring the clear-data handler so a future early-exit
  never leaves the Windows guard unreachable.
- Rewrite the clear-data Windows comment to say the Hermes chat is
  NOT killed on Windows (the previous wording implied handle cleanup
  in a branch that skips it).
- Move `platform` under `ServerOptions.lifecycle` alongside
  `supervised` / `requestShutdown`; they are the same category of
  process/environment override. Update the admin tests to match.
- Replace the 4-deep nested ternaries in RestartOverlay's message and
  hint with plain if/else blocks per the review checklist.
- Add a `RestartResponse` interface and use `api.post<RestartResponse>`
  in `triggerRestart` so the manualRestartRequired branch drops the
  four ad-hoc casts and gets contract-checked at compile time.
@Memtensor-AI

Copy link
Copy Markdown
Collaborator Author

✅ Automated Test Results: PASSED

All tests passed (91/91 executed). memos_local_plugin/unit: 82/82, memos_python_core/changed-repo-python: 9/9. Duration: 10s

Branch: bugfix/autodev-2213-20260805050240965

@Memtensor-AI Memtensor-AI added status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发 and removed status:in-progress Someone or AI is working on it | 人工或 AI 正在处理 labels Aug 5, 2026
@syzsunshine219

Copy link
Copy Markdown
Collaborator

Synced this branch with the current dev-v2.0.29 and fixed an uncovered Windows clear-data client path in 4a85a583.

POST /api/v1/admin/clear-data already returned manualRestartRequired, but SettingsView discarded the response and triggerCleared() immediately treated the still-live daemon as a successful restart. The response is now passed into the restart store, which reuses the same terminal manual-restart state as /admin/restart and skips health polling/reload.

Regression evidence:

  • before the fix, the new clear-data viewer test failed with state { phase: "restarting" }
  • focused restart/admin tests: 10/10 passed
  • full unit suite: 1302 passed, 1 skipped
  • integration suite: 4/4 passed
  • server TypeScript, viewer TypeScript, production server build, Vite viewer build, and git diff --check: passed

The PR is conflict-free and currently MERGEABLE. GitHub Actions is still experiencing an official service incident, so the fresh matrix is queued rather than executing.

@Hun-ger

Hun-ger commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

Closing as superseded by #2230, which is merged into main and implements the Windows-safe manual restart flow for unsupervised Hermes and OpenClaw runtimes.

@Hun-ger Hun-ger closed this Aug 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai:generated Generated or modified by AI | 由 AI 生成或修改 area:plugin OpenClaw & Hermes status:ready Ready for implementation; waiting for assignee or AI dispatch | 可进入实现,等待认领或派发

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants