@triclaps/cli 0.0.6 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,13 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "adapter": {
4
+ "path": "adapters/hermes_claps_adapter.py",
5
+ "requiredSymbols": [
6
+ "clarify_request_started",
7
+ "clarify_request_resolved"
8
+ ]
9
+ },
10
+ "hermes": {
11
+ "minPythonVersion": "3.11"
12
+ }
13
+ }
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Centralized source-build knobs for the minimal Hermes cloud runner.
4
+ # Build args can still override any of these values.
5
+
6
+ : "${HERMES_GIT_OWNER:=NousResearch}"
7
+ : "${HERMES_GIT_REPO:=Hermes-Agent}"
8
+ : "${HERMES_GIT_REF:=main}"
9
+ : "${HERMES_SOURCE_ARCHIVE_URL:=}"
10
+
11
+ # Minimal extras needed by the CLAPS Hermes runner.
12
+ # - modal/daytona: preserve runtime delegation backends expected by Hermes
13
+ # - messaging: enable outbound messaging tools and gateway-backed integrations
14
+ # - pty: keep terminal tool behavior aligned with the upstream Linux runtime
15
+ : "${HERMES_PYTHON_EXTRAS:=modal,daytona,messaging,pty}"
16
+
17
+ # Extra wheels not covered by Hermes core deps but required by our default toolsets.
18
+ # - Pillow: vision tool auto-resize / image re-encoding path
19
+ : "${HERMES_PYPI_EXTRA_PACKAGES:=Pillow}"
@@ -0,0 +1,198 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+
5
+ config_file="${1:-/opt/claps/hermes-source.env}"
6
+ install_root="${2:-/opt/hermes}"
7
+
8
+ if [[ ! -f "${config_file}" ]]; then
9
+ echo "[hermes-source] Missing config file: ${config_file}" >&2
10
+ exit 1
11
+ fi
12
+
13
+ # shellcheck disable=SC1090
14
+ source "${config_file}"
15
+
16
+ trim_csv_entry() {
17
+ local value="${1:-}"
18
+ value="${value#"${value%%[![:space:]]*}"}"
19
+ value="${value%"${value##*[![:space:]]}"}"
20
+ printf '%s' "${value}"
21
+ }
22
+
23
+ archive_url="${HERMES_SOURCE_ARCHIVE_URL:-}"
24
+ if [[ -z "${archive_url}" ]]; then
25
+ archive_url="https://github.com/${HERMES_GIT_OWNER}/${HERMES_GIT_REPO}/archive/${HERMES_GIT_REF}.tar.gz"
26
+ fi
27
+
28
+ workdir="$(mktemp -d)"
29
+ trap 'rm -rf "${workdir}"' EXIT
30
+
31
+ echo "[hermes-source] Fetching ${archive_url}" >&2
32
+ curl -fsSL "${archive_url}" | tar -xz --strip-components=1 -C "${workdir}"
33
+
34
+ mkdir -p "${install_root}"
35
+ cp -a "${workdir}/." "${install_root}/"
36
+
37
+ python_bin="$(command -v python3)"
38
+
39
+ ensure_uv_available() {
40
+ if command -v uv >/dev/null 2>&1; then
41
+ return 0
42
+ fi
43
+
44
+ if [[ "${CLAPS_HERMES_INSTALLER_AUTO_BOOTSTRAP_UV:-0}" != "1" ]]; then
45
+ return 1
46
+ fi
47
+
48
+ echo "[hermes-source] Bootstrapping uv via pip (CLAPS_HERMES_INSTALLER_AUTO_BOOTSTRAP_UV=1)" >&2
49
+ "${python_bin}" -m pip install --no-cache-dir "uv>=0.7,<1"
50
+
51
+ if command -v uv >/dev/null 2>&1; then
52
+ return 0
53
+ fi
54
+
55
+ local user_bin
56
+ user_bin="$("${python_bin}" -m site --user-base 2>/dev/null)/bin"
57
+ if [[ -x "${user_bin}/uv" ]]; then
58
+ export PATH="${user_bin}:${PATH}"
59
+ return 0
60
+ fi
61
+
62
+ return 1
63
+ }
64
+
65
+ if ensure_uv_available; then
66
+ installer_backend="uv"
67
+ else
68
+ installer_backend="pip"
69
+ echo "[hermes-source] uv not available; falling back to python -m venv + pip (slower)." >&2
70
+ fi
71
+
72
+ # Hermes requires Python >=3.11. Detect current python3 and decide how to build the venv.
73
+ HERMES_MIN_PYTHON_VERSION="${HERMES_MIN_PYTHON_VERSION:-3.11}"
74
+
75
+ python_version="$("${python_bin}" -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")' 2>/dev/null || echo "0.0")"
76
+ python_too_old=0
77
+ if ! "${python_bin}" -c "import sys; req=tuple(int(x) for x in '${HERMES_MIN_PYTHON_VERSION}'.split('.')); sys.exit(0 if sys.version_info[:2] >= req else 1)" 2>/dev/null; then
78
+ python_too_old=1
79
+ fi
80
+
81
+ if [[ "${python_too_old}" == "1" ]]; then
82
+ if [[ "${installer_backend}" == "uv" ]]; then
83
+ echo "[hermes-source] python3 on PATH is ${python_version} (< ${HERMES_MIN_PYTHON_VERSION}); asking uv to auto-resolve a compatible interpreter." >&2
84
+ venv_python_arg="${HERMES_MIN_PYTHON_VERSION}"
85
+ # Force uv to use its python-build-standalone distribution rather than any
86
+ # too-old system interpreter it might still see; this also gives consistent
87
+ # ABI tags so prebuilt wheels (cbor2, pydantic-core, etc.) match.
88
+ uv_python_pref="--python-preference=only-managed"
89
+ else
90
+ echo "[hermes-source] ERROR: python3 on PATH is ${python_version} but Hermes requires >=${HERMES_MIN_PYTHON_VERSION}." >&2
91
+ echo "[hermes-source] Install Python ${HERMES_MIN_PYTHON_VERSION}+ (e.g. via brew/conda) or install uv (https://docs.astral.sh/uv/) so the installer can auto-provision a compatible interpreter." >&2
92
+ exit 1
93
+ fi
94
+ else
95
+ venv_python_arg="${python_bin}"
96
+ uv_python_pref=""
97
+ fi
98
+
99
+ if [[ "${installer_backend}" == "uv" ]]; then
100
+ if [[ -n "${uv_python_pref}" ]]; then
101
+ uv venv "${install_root}/.venv" --python "${venv_python_arg}" "${uv_python_pref}"
102
+ else
103
+ uv venv "${install_root}/.venv" --python "${venv_python_arg}"
104
+ fi
105
+ else
106
+ "${python_bin}" -m venv "${install_root}/.venv"
107
+ "${install_root}/.venv/bin/pip" install --no-cache-dir --upgrade pip
108
+ fi
109
+
110
+ extras_spec=""
111
+ IFS=',' read -r -a hermes_extras <<<"${HERMES_PYTHON_EXTRAS:-}"
112
+ normalized_extras=()
113
+ for extra in "${hermes_extras[@]}"; do
114
+ trimmed_extra="$(trim_csv_entry "${extra}")"
115
+ if [[ -n "${trimmed_extra}" ]]; then
116
+ normalized_extras+=("${trimmed_extra}")
117
+ fi
118
+ done
119
+
120
+ if [[ ${#normalized_extras[@]} -gt 0 ]]; then
121
+ extras_spec="["
122
+ for extra in "${normalized_extras[@]}"; do
123
+ if [[ "${extras_spec}" != "[" ]]; then
124
+ extras_spec+=","
125
+ fi
126
+ extras_spec+="${extra}"
127
+ done
128
+ extras_spec+="]"
129
+ fi
130
+
131
+ if [[ "${installer_backend}" == "uv" ]]; then
132
+ uv pip install --python "${install_root}/.venv/bin/python" "${install_root}${extras_spec}"
133
+ else
134
+ "${install_root}/.venv/bin/pip" install --no-cache-dir "${install_root}${extras_spec}"
135
+ fi
136
+
137
+ extra_packages=()
138
+ IFS=',' read -r -a pypi_packages <<<"${HERMES_PYPI_EXTRA_PACKAGES:-}"
139
+ for package in "${pypi_packages[@]}"; do
140
+ trimmed_package="$(trim_csv_entry "${package}")"
141
+ if [[ -n "${trimmed_package}" ]]; then
142
+ extra_packages+=("${trimmed_package}")
143
+ fi
144
+ done
145
+
146
+ if [[ ${#extra_packages[@]} -gt 0 ]]; then
147
+ if [[ "${installer_backend}" == "uv" ]]; then
148
+ uv pip install --python "${install_root}/.venv/bin/python" "${extra_packages[@]}"
149
+ else
150
+ "${install_root}/.venv/bin/pip" install --no-cache-dir "${extra_packages[@]}"
151
+ fi
152
+ fi
153
+
154
+ # Optional: install Hermes' npm-side deps (agent-browser, camofox-browser).
155
+ # These power the browser tool. Cloud images skip this stage to keep size down.
156
+ node_install_mode="none"
157
+ if [[ -f "${install_root}/package.json" && "${CLAPS_HERMES_INSTALLER_SKIP_NODE:-0}" != "1" ]]; then
158
+ if command -v pnpm >/dev/null 2>&1; then
159
+ echo "[hermes-source] Installing Hermes npm deps via pnpm" >&2
160
+ (cd "${install_root}" && pnpm install --prod --silent --no-frozen-lockfile)
161
+ node_install_mode="pnpm"
162
+ elif command -v npm >/dev/null 2>&1; then
163
+ echo "[hermes-source] Installing Hermes npm deps via npm" >&2
164
+ (cd "${install_root}" && npm install --omit=dev --silent --no-audit --no-fund)
165
+ node_install_mode="npm"
166
+ else
167
+ echo "[hermes-source] No pnpm/npm on PATH; skipping browser tool install. Install pnpm/npm and re-run with --repair to enable browser tools." >&2
168
+ fi
169
+ fi
170
+
171
+ # Cleanup directories that are not used at runtime. Preserve node_modules
172
+ # only when we just installed it; otherwise wipe whatever shipped in the tarball.
173
+ keep_node_modules=0
174
+ if [[ "${node_install_mode}" != "none" ]]; then
175
+ keep_node_modules=1
176
+ fi
177
+
178
+ cleanup_targets=(
179
+ "${install_root}/.playwright"
180
+ "${install_root}/optional-skills"
181
+ "${install_root}/tests"
182
+ "${install_root}/tui_gateway"
183
+ "${install_root}/ui-tui"
184
+ "${install_root}/web"
185
+ "${install_root}/website"
186
+ )
187
+ if [[ "${keep_node_modules}" -eq 0 ]]; then
188
+ cleanup_targets+=("${install_root}/node_modules")
189
+ fi
190
+ rm -rf "${cleanup_targets[@]}"
191
+
192
+ # Marker for the TS layer to know what we installed.
193
+ cat >"${install_root}/.install-state.json" <<JSON
194
+ {
195
+ "pythonBackend": "${installer_backend}",
196
+ "nodeInstallMode": "${node_install_mode}"
197
+ }
198
+ JSON