Skip to content

Fix #1915: fix(memos-local-plugin): bridge status detection misses hermes chat with global #1925

Open
Memtensor-AI wants to merge 1 commit into
dev-20260615-v2.0.20from
bugfix/autodev-1915
Open

Fix #1915: fix(memos-local-plugin): bridge status detection misses hermes chat with global #1925
Memtensor-AI wants to merge 1 commit into
dev-20260615-v2.0.20from
bugfix/autodev-1915

Conversation

@Memtensor-AI

Copy link
Copy Markdown
Collaborator

Description

Fixes #1915. isHermesChatRunning() in apps/memos-local-plugin/bridge.cts was using pgrep -f "hermes chat" as a literal substring, so it silently missed any session launched with global flags before the subcommand (e.g. hermes --skills memory-routing chat). In daemon mode this left applyStaleRule() permanently stuck on "disconnected" instead of upgrading to "reconnecting". Stdio mode was unaffected (it manages its own status via markConnected / markDisconnected).

The pattern + helper were extracted into a new ESM module apps/memos-local-plugin/bridge/hermes-process.ts, exporting HERMES_CHAT_PROCESS_PATTERN = "hermes\\s.*chat\\b", a JS-side matchesHermesChatCommandLine(cmd) predicate, and an isHermesChatRunning(execFile?) wrapper with injectable execFile for testing. bridge.cts now loads the helper via the same runtimeModule() / importEsm() machinery as its other dependencies and threads it into createBridgeStatusTracker via DI. The new regex covers hermes chat, hermes chat --…, and hermes --… chat while still rejecting hermesctl, hermes status, and unrelated processes thanks to the \s anchor and the \b word boundary.

Verification: pnpm exec vitest run tests/unit/bridge/ → 28 passed (13 new regex / pgrep-wrapper assertions + 15 existing methods/stdio); pnpm run lint (tsc --noEmit) → exit 0; live-fire on Linux spawned a fake /usr/local/bin/hermes --skills memory-routing chat process and confirmed the old literal pattern missed it while the new regex matched it. Two unit failures in tests/unit/storage/{migrator,traces-count}.test.ts were confirmed pre-existing on the base branch (stashed this diff and re-ran) and are unrelated.

Branch bugfix/autodev-1915 pushed to origin at commit ccb369da. Reviewers @MatthewZhuang @CarltonXiang @syzsunshine219.

Related Issue (Required): Fixes #1915

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

@MatthewZhuang, @CarltonXiang, @syzsunshine219 please review this PR.

Reviewer Checklist

`isHermesChatRunning()` in `bridge.cts` was using `pgrep -f "hermes
chat"` as a literal substring, which only matched when those two tokens
were adjacent on the process command line. The `hermes` CLI accepts
global flags (`--skills`, `-m`, `--provider`) before the subcommand, so
real invocations such as `hermes --skills memory-routing chat` showed up
in `/proc/<pid>/cmdline` with arbitrary tokens between `hermes` and
`chat` and were silently missed. In daemon mode this left
`applyStaleRule()` permanently stuck on `"disconnected"` instead of
upgrading to `"reconnecting"` (#1915).

Extracted the pattern + helper into a new `bridge/hermes-process.ts`
ESM module so it is unit-testable, and replaced the literal with the
regex `hermes\s.*chat\b`. That covers the three documented invocation
shapes -- `hermes chat`, `hermes chat --...`, and `hermes --... chat` --
while still rejecting `hermesctl`, `hermes status`, and unrelated
processes thanks to the `\s` anchor and the `\b` word boundary.
`bridge.cts` now imports the helper via the existing
`runtimeModule()` / `importEsm()` machinery and passes it into
`createBridgeStatusTracker` via DI, keeping the bridge surface
identical (same `execFileSync("pgrep", ...)` call site).

Verification:

  - `pnpm exec vitest run tests/unit/bridge/` -> 28 passed (13 new +
    15 existing methods/stdio).
  - `pnpm run lint` (tsc --noEmit) -> exit 0.
  - Live-fire on Linux: spawned a fake
    `/usr/local/bin/hermes --skills memory-routing chat` process,
    confirmed old literal pattern missed it and the new regex
    matched it.
  - Wider failures in `tests/unit/storage/{migrator,traces-count}`
    are pre-existing on the base branch (verified by stashing this
    diff and re-running) and unrelated.

Stdio mode (the default Hermes provider / systemd path) is unchanged:
it manages its own status via `markConnected` / `markDisconnected` and
never calls `isHermesChatRunning`.
@Memtensor-AI

Copy link
Copy Markdown
Collaborator Author

✅ Automated Test Results: PASSED

All tests passed (35/35 executed, 35 skipped). memos_local_plugin/smoke: 0/0, memos_local_plugin/contract: 35 passed, 35 skipped. Duration: 4s

Branch: bugfix/autodev-1915

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-generated bug Something isn't working | 功能异常

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants