Skip to content

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

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

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.

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.

3 participants