Pre-submission checklist | 提交前检查
Problem Statement | 问题陈述
The Hermes adapter pins the viewer/daemon port to 18800 with no override, so on a host where a Hermes gateway is already running there is no supported way to bring up a second MemOS instance on a different port — for example to point a measurement harness at an isolated MEMOS_HOME snapshot, or to run a dev instance alongside a production one.
Verified against main (176d4f67):
1. The port is a module constant, and the design is explicitly a singleton.
apps/memos-local-plugin/adapters/hermes/memos_provider/daemon_manager.py:55 → HERMES_VIEWER_PORT = 18800. It is used by the health probe (:287, :291), the daemon spawn and its readiness checks (:391, :398, :416, :423, :476, :481), and the zombie scan matches the literal ":18800" (:534, :547). The docstring at :364 states it: "Ensure the singleton Hermes Viewer daemon owns :18800."
2. The config field exists but its value is discarded.
memos_provider/__init__.py:1693-1697 exposes a viewer_port setup field (default 18800), but save_config (:1744-1748) ignores what the user supplied and writes 18800, with the comment "the Hermes adapter owns :18800. Persist the effective value so the YAML file never advertises a port the runtime will not bind."
3. No environment override exists.
The adapter reads MEMOS_HOME, MEMOS_CONFIG_FILE, MEMOS_HERMES_BRIDGE_MODE, MEMOS_HERMES_LONG_RPC_TIMEOUT, MEMOS_HERMES_PREFETCH_RPC_TIMEOUT and MEMOS_NODE_BINARY. None of them is the port.
The consequence is that the singleton assumption is unfalsifiable: a second instance cannot be isolated, because every probe and every client resolves to 127.0.0.1:18800 regardless of which home that instance was given. Setting MEMOS_HOME to a scratch home is not enough on its own — the listener it should be talking to is the one already running.
Related but distinct: #2212 (closed) covers the viewer UI clobbering viewer.port; its resolution keeps the adapter owning the value. This request is the inverse — an explicit, opt-in override.
Proposed change: read the port from an environment variable (e.g. MEMOS_VIEWER_PORT, name at your discretion) when resolving the viewer runtime, defaulting to 18800, and use that value in the probe, the daemon spawn/readiness checks, the zombie scan and any HTTP client. Honour a configured viewer_port rather than discarding it. With the variable unset, production behaviour is byte-for-byte unchanged.
Willingness to Implement | 实现意愿
Pre-submission checklist | 提交前检查
Problem Statement | 问题陈述
The Hermes adapter pins the viewer/daemon port to
18800with no override, so on a host where a Hermes gateway is already running there is no supported way to bring up a second MemOS instance on a different port — for example to point a measurement harness at an isolatedMEMOS_HOMEsnapshot, or to run a dev instance alongside a production one.Verified against
main(176d4f67):1. The port is a module constant, and the design is explicitly a singleton.
apps/memos-local-plugin/adapters/hermes/memos_provider/daemon_manager.py:55→HERMES_VIEWER_PORT = 18800. It is used by the health probe (:287,:291), the daemon spawn and its readiness checks (:391,:398,:416,:423,:476,:481), and the zombie scan matches the literal":18800"(:534,:547). The docstring at:364states it: "Ensure the singleton Hermes Viewer daemon owns :18800."2. The config field exists but its value is discarded.
memos_provider/__init__.py:1693-1697exposes aviewer_portsetup field (default18800), butsave_config(:1744-1748) ignores what the user supplied and writes18800, with the comment "the Hermes adapter owns :18800. Persist the effective value so the YAML file never advertises a port the runtime will not bind."3. No environment override exists.
The adapter reads
MEMOS_HOME,MEMOS_CONFIG_FILE,MEMOS_HERMES_BRIDGE_MODE,MEMOS_HERMES_LONG_RPC_TIMEOUT,MEMOS_HERMES_PREFETCH_RPC_TIMEOUTandMEMOS_NODE_BINARY. None of them is the port.The consequence is that the singleton assumption is unfalsifiable: a second instance cannot be isolated, because every probe and every client resolves to
127.0.0.1:18800regardless of which home that instance was given. SettingMEMOS_HOMEto a scratch home is not enough on its own — the listener it should be talking to is the one already running.Related but distinct: #2212 (closed) covers the viewer UI clobbering
viewer.port; its resolution keeps the adapter owning the value. This request is the inverse — an explicit, opt-in override.Proposed change: read the port from an environment variable (e.g.
MEMOS_VIEWER_PORT, name at your discretion) when resolving the viewer runtime, defaulting to18800, and use that value in the probe, the daemon spawn/readiness checks, the zombie scan and any HTTP client. Honour a configuredviewer_portrather than discarding it. With the variable unset, production behaviour is byte-for-byte unchanged.Willingness to Implement | 实现意愿