v0.7: one-click install — pyproject, console scripts, user units, hermes wiring
A clone + ./install.sh + ./launch-brave.sh + sign in once. Nothing else. pyproject.toml declares the one real dependency (websockets) and maps the repo-root-is-the-package layout, which retires the PYTHONPATH=<parent> line every unit used to carry. cli.py backs three console scripts. They exist because `python3 -m socialmag` run from INSIDE a clone dies at `import asyncio`: the repo root is the package dir, so it ships selectors.py and queue.py, and python puts the current directory first on sys.path. `cd socialmag` is the first thing anyone does after a clone, so the documented workaround failed at exactly the moment it would be tried. A generated bin/ script never puts cwd on sys.path. The same trap bit `python3 -m venv` inside install.sh — the installer was broken by the thing it exists to fix. Every python3 call now runs from /. deploy/user/*.in replaces root system units with systemd --user templates: no User=, WantedBy=default.target, venv paths, @REPO@/@VENV@/@CDP_ENDPOINT@ substituted at install time. deploy/home/ is untouched and still live here. launch-brave.sh carries --disable-background-timer-throttling. That is load-bearing, not tidiness: five of six platforms are read in a hidden tab, and a throttled background tab stops running the timers those pages use to fetch their own data — the reads come back empty with no error. install.sh checks the mcp package in hermes's own interpreter and refuses to continue without it. Hermes treats mcp as optional and silently no-ops the whole subsystem when it is missing, so a server that never loaded looks exactly like one that loaded and did nothing. It will not merge into an existing mcp_servers: key — it backs up config.yaml and appends only when the key is absent, otherwise it prints the block. Blind YAML merging is how someone's other servers disappear. Verified end-to-end in a sandbox with a fake HOME and stubbed systemctl: real MCP initialize handshake from inside the repo dir returns all 7 tools; hermes's own yaml parser re-reads the written config with every pre-existing key intact; a second run leaves the mcp_servers key count at 1; launch-brave.sh exits 1 against a busy port; no unsubstituted @PLACEHOLDER@ in any rendered unit. Not fixed, pre-existing: server.py reports SERVER_VERSION 0.1.0 while the repo is at v0.7. The handshake shows 0.1.0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
"""Console-script entry points.
|
||||
|
||||
These exist for one reason: `python3 -m socialmag` from inside the repo
|
||||
directory dies at `import asyncio`.
|
||||
|
||||
The repo root is the package dir, so it holds `selectors.py` and `queue.py` —
|
||||
names the stdlib also uses. `-m` puts the current directory first on
|
||||
`sys.path`, so asyncio's own `import selectors` finds ours and fails with
|
||||
`module 'selectors' has no attribute 'SelectSelector'`. Running from one
|
||||
directory up avoids it, which is what the old PYTHONPATH units did.
|
||||
|
||||
A console script is generated in the venv's `bin/` and run by absolute path, so
|
||||
the current directory never reaches `sys.path` at all. `cd socialmag` — the
|
||||
first thing anyone does after a clone — stops being a trap.
|
||||
|
||||
The `-m` forms still work from outside the repo directory.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
from . import openbridge as _openbridge
|
||||
from . import refresher as _refresher
|
||||
from . import server as _server
|
||||
|
||||
|
||||
def serve() -> None:
|
||||
"""socialmag — the stdio MCP server."""
|
||||
try:
|
||||
asyncio.run(_server.main())
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
|
||||
def refresh() -> int:
|
||||
"""socialmag-refresh — one refresher pass, then exit."""
|
||||
return asyncio.run(_refresher.main())
|
||||
|
||||
|
||||
def openbridge() -> None:
|
||||
"""socialmag-openbridge — the localhost open_link HTTP shim."""
|
||||
_openbridge.main()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(serve())
|
||||
Reference in New Issue
Block a user