@@ -7,8 +7,146 @@ set -euo pipefail
77# bash install.sh [/path/to/hermes-agent]
88#
99# Prerequisites:
10- # - Node.js >= 18
1110# - hermes-agent repository cloned locally
11+ # - Node.js >= 18 (auto-installed if missing)
12+
13+ GREEN=' \033[0;32m'
14+ BLUE=' \033[0;34m'
15+ YELLOW=' \033[1;33m'
16+ RED=' \033[0;31m'
17+ BOLD=' \033[1m'
18+ NC=' \033[0m'
19+
20+ info () { echo -e " ${BLUE} $1 ${NC} " ; }
21+ success () { echo -e " ${GREEN} $1 ${NC} " ; }
22+ warn () { echo -e " ${YELLOW} $1 ${NC} " ; }
23+ error () { echo -e " ${RED} $1 ${NC} " ; }
24+
25+ # ─── Node.js auto-install helpers ───
26+
27+ node_major_version () {
28+ if ! command -v node > /dev/null 2>&1 ; then
29+ echo " 0"
30+ return 0
31+ fi
32+ local node_version
33+ node_version=" $( node -v 2> /dev/null || true) "
34+ node_version=" ${node_version# v} "
35+ echo " ${node_version%% .* } "
36+ }
37+
38+ run_with_privilege () {
39+ if [[ " $( id -u) " -eq 0 ]]; then
40+ " $@ "
41+ else
42+ sudo " $@ "
43+ fi
44+ }
45+
46+ download_to_file () {
47+ local url=" $1 "
48+ local output=" $2 "
49+ if command -v curl > /dev/null 2>&1 ; then
50+ curl -fsSL --proto ' =https' --tlsv1.2 " $url " -o " $output "
51+ return 0
52+ fi
53+ if command -v wget > /dev/null 2>&1 ; then
54+ wget -q --https-only --secure-protocol=TLSv1_2 " $url " -O " $output "
55+ return 0
56+ fi
57+ return 1
58+ }
59+
60+ install_node22 () {
61+ local os_name
62+ os_name=" $( uname -s) "
63+
64+ if [[ " $os_name " == " Darwin" ]]; then
65+ if ! command -v brew > /dev/null 2>&1 ; then
66+ error " Homebrew is required to auto-install Node.js on macOS"
67+ error " Install Homebrew first: https://brew.sh"
68+ exit 1
69+ fi
70+ info " Auto-installing Node.js 22 via Homebrew..."
71+ brew install node@22 > /dev/null
72+ brew link node@22 --overwrite --force > /dev/null 2>&1 || true
73+ local brew_node_prefix
74+ brew_node_prefix=" $( brew --prefix node@22 2> /dev/null || true) "
75+ if [[ -n " $brew_node_prefix " && -x " ${brew_node_prefix} /bin/node" ]]; then
76+ export PATH=" ${brew_node_prefix} /bin:${PATH} "
77+ fi
78+ return 0
79+ fi
80+
81+ if [[ " $os_name " == " Linux" ]]; then
82+ info " Auto-installing Node.js 22 on Linux..."
83+ local tmp_script
84+ tmp_script=" $( mktemp) "
85+ if command -v apt-get > /dev/null 2>&1 ; then
86+ if ! download_to_file " https://deb.nodesource.com/setup_22.x" " $tmp_script " ; then
87+ error " Failed to download NodeSource setup script"
88+ rm -f " $tmp_script "
89+ exit 1
90+ fi
91+ run_with_privilege bash " $tmp_script "
92+ run_with_privilege apt-get update -qq
93+ run_with_privilege apt-get install -y -qq nodejs
94+ rm -f " $tmp_script "
95+ return 0
96+ fi
97+ if command -v dnf > /dev/null 2>&1 ; then
98+ if ! download_to_file " https://rpm.nodesource.com/setup_22.x" " $tmp_script " ; then
99+ error " Failed to download NodeSource setup script"
100+ rm -f " $tmp_script "
101+ exit 1
102+ fi
103+ run_with_privilege bash " $tmp_script "
104+ run_with_privilege dnf install -y -q nodejs
105+ rm -f " $tmp_script "
106+ return 0
107+ fi
108+ if command -v yum > /dev/null 2>&1 ; then
109+ if ! download_to_file " https://rpm.nodesource.com/setup_22.x" " $tmp_script " ; then
110+ error " Failed to download NodeSource setup script"
111+ rm -f " $tmp_script "
112+ exit 1
113+ fi
114+ run_with_privilege bash " $tmp_script "
115+ run_with_privilege yum install -y -q nodejs
116+ rm -f " $tmp_script "
117+ return 0
118+ fi
119+ rm -f " $tmp_script "
120+ fi
121+
122+ error " Unsupported platform for auto-install. Please install Node.js >= 18 manually."
123+ exit 1
124+ }
125+
126+ ensure_node () {
127+ local required_major=18
128+ local current_major
129+ current_major=" $( node_major_version) "
130+
131+ if [[ " $current_major " =~ ^[0-9]+$ ]] && (( current_major >= required_major )) ; then
132+ success " ✓ Node.js $( node -v) "
133+ return 0
134+ fi
135+
136+ warn " Node.js >= ${required_major} is required but not found. Auto-installing..."
137+ install_node22
138+
139+ current_major=" $( node_major_version) "
140+ if [[ " $current_major " =~ ^[0-9]+$ ]] && (( current_major >= required_major )) ; then
141+ success " ✓ Node.js installed: $( node -v) "
142+ return 0
143+ fi
144+
145+ error " Node.js installation failed — still below >= ${required_major} ."
146+ exit 1
147+ }
148+
149+ # ─── Main ───
12150
13151SCRIPT_DIR=" $( cd " $( dirname " $0 " ) " && pwd) "
14152MEMOS_PLUGIN_DIR=" $( cd " $SCRIPT_DIR /../.." && pwd) "
29167
30168TARGET_DIR=" $HERMES_REPO /plugins/memory/memtensor"
31169
32- echo " === MemTensor Memory Plugin Installer (hermes-agent) ==="
170+ echo -e " ${BOLD} === MemTensor Memory Plugin Installer (hermes-agent) ===${NC} "
33171echo " "
34- echo " Plugin source: $SCRIPT_DIR "
35- echo " Plugin root: $MEMOS_PLUGIN_DIR "
36- echo " Hermes repo: $HERMES_REPO "
37- echo " Install target: $TARGET_DIR "
172+ info " Plugin source: $SCRIPT_DIR "
173+ info " Plugin root: $MEMOS_PLUGIN_DIR "
174+ info " Hermes repo: $HERMES_REPO "
175+ info " Install target: $TARGET_DIR "
38176echo " "
39177
40178# ─── Pre-flight checks ───
41179
42180if [ ! -f " $HERMES_REPO /agent/memory_provider.py" ]; then
43- echo " ERROR: $HERMES_REPO does not look like a hermes-agent repository."
44- exit 1
45- fi
46-
47- if ! command -v node & > /dev/null; then
48- echo " ERROR: Node.js is required (>= 18). Please install it first."
49- exit 1
50- fi
51-
52- NODE_VERSION=$( node -v | sed ' s/v//' | cut -d. -f1)
53- if [ " $NODE_VERSION " -lt 18 ]; then
54- echo " ERROR: Node.js >= 18 is required. Current: $( node -v) "
181+ error " ERROR: $HERMES_REPO does not look like a hermes-agent repository."
55182 exit 1
56183fi
57184
58- echo " ✓ Node.js $( node -v ) "
185+ ensure_node
59186
60187# ─── Install plugin dependencies ───
61188
62189echo " "
63- echo " Installing plugin dependencies..."
190+ info " Installing plugin dependencies..."
64191cd " $MEMOS_PLUGIN_DIR "
65192
66193if command -v pnpm & > /dev/null; then
67194 pnpm install --frozen-lockfile 2> /dev/null || pnpm install
68195elif command -v npm & > /dev/null; then
69196 npm install
70197else
71- echo " ERROR: npm or pnpm is required."
198+ error " ERROR: npm or pnpm is required."
72199 exit 1
73200fi
74201
75- echo " ✓ Dependencies installed"
202+ success " ✓ Dependencies installed"
76203
77204# ─── Record bridge path for runtime discovery ───
78205
79206BRIDGE_CTS=" $MEMOS_PLUGIN_DIR /bridge.cts"
80207echo " $BRIDGE_CTS " > " $SCRIPT_DIR /bridge_path.txt"
81208
82209if [ -f " $BRIDGE_CTS " ]; then
83- echo " ✓ Bridge script found: $BRIDGE_CTS "
210+ success " ✓ Bridge script found: $BRIDGE_CTS "
84211else
85- echo " WARNING: bridge.cts not found at $BRIDGE_CTS "
86- echo " Make sure it exists before using the plugin."
212+ warn " WARNING: bridge.cts not found at $BRIDGE_CTS "
213+ warn " Make sure it exists before using the plugin."
87214fi
88215
89216# ─── Create symlink in hermes-agent plugins/memory/ ───
90217
91218echo " "
92- echo " Creating symlink: $TARGET_DIR -> $SCRIPT_DIR "
219+ info " Creating symlink: $TARGET_DIR -> $SCRIPT_DIR "
93220
94221if [ -L " $TARGET_DIR " ]; then
95222 rm " $TARGET_DIR "
96- echo " (removed old symlink)"
223+ info " (removed old symlink)"
97224elif [ -d " $TARGET_DIR " ]; then
98225 rm -rf " $TARGET_DIR "
99- echo " (removed old directory)"
226+ info " (removed old directory)"
100227fi
101228
102229ln -s " $SCRIPT_DIR " " $TARGET_DIR "
103- echo " ✓ Symlink created"
230+ success " ✓ Symlink created"
104231
105232echo " "
106- echo " === Installation complete ==="
233+ echo -e " ${BOLD} === Installation complete ===${NC} "
107234echo " "
108- echo " Activate the plugin by editing ~/.hermes/config.yaml:"
235+ info " Activate the plugin by editing ~/.hermes/config.yaml:"
109236echo " "
110237echo " memory:"
111238echo " provider: memtensor"
112239echo " "
113- echo " Then start hermes normally. The bridge daemon and memory viewer"
114- echo " will start automatically on first session."
240+ info " Then start hermes normally. The bridge daemon and memory viewer"
241+ info " will start automatically on first session."
115242echo " "
116- echo " Memory Viewer: http://127.0.0.1:18901"
243+ success " Memory Viewer: http://127.0.0.1:18901"
117244echo " "
118- echo " Optional environment variables:"
245+ info " Optional environment variables:"
119246echo " MEMOS_STATE_DIR - Override memory database location"
120247echo " MEMOS_DAEMON_PORT - Bridge daemon TCP port (default: 18990)"
121248echo " MEMOS_VIEWER_PORT - Memory viewer HTTP port (default: 18899)"
0 commit comments