@hitechclaw/clawspark 2.0.0

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/LICENSE +21 -0
  3. package/README.md +378 -0
  4. package/clawspark +2715 -0
  5. package/configs/models.yaml +108 -0
  6. package/configs/skill-packs.yaml +44 -0
  7. package/configs/skills.yaml +37 -0
  8. package/install.sh +387 -0
  9. package/lib/common.sh +249 -0
  10. package/lib/detect-hardware.sh +156 -0
  11. package/lib/diagnose.sh +636 -0
  12. package/lib/render-diagram.sh +47 -0
  13. package/lib/sandbox-commands.sh +415 -0
  14. package/lib/secure.sh +244 -0
  15. package/lib/select-model.sh +442 -0
  16. package/lib/setup-browser.sh +138 -0
  17. package/lib/setup-dashboard.sh +228 -0
  18. package/lib/setup-inference.sh +128 -0
  19. package/lib/setup-mcp.sh +142 -0
  20. package/lib/setup-messaging.sh +242 -0
  21. package/lib/setup-models.sh +121 -0
  22. package/lib/setup-openclaw.sh +808 -0
  23. package/lib/setup-sandbox.sh +188 -0
  24. package/lib/setup-skills.sh +113 -0
  25. package/lib/setup-systemd.sh +224 -0
  26. package/lib/setup-tailscale.sh +188 -0
  27. package/lib/setup-voice.sh +101 -0
  28. package/lib/skill-audit.sh +449 -0
  29. package/lib/verify.sh +177 -0
  30. package/package.json +57 -0
  31. package/scripts/release.sh +133 -0
  32. package/uninstall.sh +161 -0
  33. package/v2/README.md +50 -0
  34. package/v2/configs/providers.yaml +79 -0
  35. package/v2/configs/skills.yaml +36 -0
  36. package/v2/install.sh +116 -0
  37. package/v2/lib/common.sh +285 -0
  38. package/v2/lib/detect-hardware.sh +119 -0
  39. package/v2/lib/select-runtime.sh +273 -0
  40. package/v2/lib/setup-extras.sh +95 -0
  41. package/v2/lib/setup-openclaw.sh +187 -0
  42. package/v2/lib/setup-provider.sh +131 -0
  43. package/v2/lib/verify.sh +133 -0
  44. package/web/index.html +1835 -0
  45. package/web/install.sh +387 -0
  46. package/web/logo-hero.svg +11 -0
  47. package/web/logo-icon.svg +12 -0
  48. package/web/logo.svg +17 -0
  49. package/web/vercel.json +8 -0
package/lib/common.sh ADDED
@@ -0,0 +1,249 @@
1
+ #!/usr/bin/env bash
2
+ # lib/common.sh — Shared utilities sourced by all clawspark scripts.
3
+ # Provides logging, prompts, color constants, spinner, and global paths.
4
+ set -euo pipefail
5
+
6
+ # ── Global paths ────────────────────────────────────────────────────────────
7
+ CLAWSPARK_DIR="${CLAWSPARK_DIR:-${HOME}/.clawspark}"
8
+ CLAWSPARK_LOG="${CLAWSPARK_LOG:-${CLAWSPARK_DIR}/install.log}"
9
+ CLAWSPARK_DEFAULTS="${CLAWSPARK_DEFAULTS:-false}"
10
+
11
+ # ── Color constants ─────────────────────────────────────────────────────────
12
+ if [[ -t 1 ]] && command -v tput &>/dev/null && [[ "$(tput colors 2>/dev/null || echo 0)" -ge 8 ]]; then
13
+ RED=$(tput setaf 1)
14
+ GREEN=$(tput setaf 2)
15
+ YELLOW=$(tput setaf 3)
16
+ BLUE=$(tput setaf 4)
17
+ CYAN=$(tput setaf 6)
18
+ BOLD=$(tput bold)
19
+ RESET=$(tput sgr0)
20
+ else
21
+ RED=$'\033[0;31m'
22
+ GREEN=$'\033[0;32m'
23
+ YELLOW=$'\033[0;33m'
24
+ BLUE=$'\033[0;34m'
25
+ CYAN=$'\033[0;36m'
26
+ BOLD=$'\033[1m'
27
+ RESET=$'\033[0m'
28
+ fi
29
+
30
+ # ── Helpers (Bash 3.2 compatible) ───────────────────────────────────────────
31
+ to_lower() { echo "$1" | tr '[:upper:]' '[:lower:]'; }
32
+
33
+ # ── Logging ─────────────────────────────────────────────────────────────────
34
+ _ts() { date '+%H:%M:%S'; }
35
+
36
+ log_info() {
37
+ printf '%s[%s]%s %s\n' "${BLUE}" "$(_ts)" "${RESET}" "$*"
38
+ _log_to_file "INFO" "$*"
39
+ }
40
+
41
+ log_warn() {
42
+ printf '%s[%s] WARNING:%s %s\n' "${YELLOW}" "$(_ts)" "${RESET}" "$*" >&2
43
+ _log_to_file "WARN" "$*"
44
+ }
45
+
46
+ log_error() {
47
+ printf '%s[%s] ERROR:%s %s\n' "${RED}" "$(_ts)" "${RESET}" "$*" >&2
48
+ _log_to_file "ERROR" "$*"
49
+ }
50
+
51
+ log_success() {
52
+ printf '%s[%s] OK:%s %s\n' "${GREEN}" "$(_ts)" "${RESET}" "$*"
53
+ _log_to_file "OK" "$*"
54
+ }
55
+
56
+ _log_to_file() {
57
+ local level="$1"; shift
58
+ if [[ -d "${CLAWSPARK_DIR}" ]]; then
59
+ printf '[%s] [%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "${level}" "$*" \
60
+ >> "${CLAWSPARK_LOG}" 2>/dev/null || true
61
+ fi
62
+ }
63
+
64
+ # ── Prompt helpers ──────────────────────────────────────────────────────────
65
+
66
+ # prompt_choice QUESTION OPTIONS_ARRAY DEFAULT_INDEX
67
+ # Displays numbered options and returns the selected value.
68
+ # If CLAWSPARK_DEFAULTS=true, returns the default without prompting.
69
+ #
70
+ # Usage:
71
+ # options=("Option A" "Option B" "Option C")
72
+ # result=$(prompt_choice "Pick one:" options 0)
73
+ prompt_choice() {
74
+ local question="$1"
75
+ local options_name="$2" # array name (Bash 3.2 compatible: no nameref)
76
+ local default_idx="${3:-0}"
77
+ local count
78
+ eval "count=\${#${options_name}[@]}"
79
+
80
+ # If running in defaults mode, return default immediately
81
+ if [[ "${CLAWSPARK_DEFAULTS}" == "true" ]]; then
82
+ eval "printf '%s' \"\${${options_name}[$default_idx]}\""
83
+ return 0
84
+ fi
85
+
86
+ # Print menu to /dev/tty so it's visible even inside $(...) capture
87
+ printf '\n%s%s%s\n' "${BOLD}" "${question}" "${RESET}" >/dev/tty
88
+ local i
89
+ for i in $(seq 0 $(( count - 1 ))); do
90
+ local marker=""
91
+ if [[ "$i" -eq "$default_idx" ]]; then
92
+ marker=" ${CYAN}(default)${RESET}"
93
+ fi
94
+ local opt
95
+ eval "opt=\${${options_name}[$i]}"
96
+ printf ' %s%d)%s %s%s\n' "${GREEN}" $(( i + 1 )) "${RESET}" "${opt}" "${marker}" >/dev/tty
97
+ done
98
+
99
+ local selection
100
+ while true; do
101
+ printf '%s> %s' "${BOLD}" "${RESET}" >/dev/tty
102
+ read -r selection </dev/tty || selection=""
103
+ # Empty input → default
104
+ if [[ -z "${selection}" ]]; then
105
+ eval "printf '%s' \"\${${options_name}[$default_idx]}\""
106
+ return 0
107
+ fi
108
+ # Validate numeric input
109
+ if [[ "${selection}" =~ ^[0-9]+$ ]] && (( selection >= 1 && selection <= count )); then
110
+ eval "printf '%s' \"\${${options_name}[$(( selection - 1 ))]}\""
111
+ return 0
112
+ fi
113
+ printf ' %sPlease enter a number between 1 and %d%s\n' "${YELLOW}" "${count}" "${RESET}" >/dev/tty
114
+ done
115
+ }
116
+
117
+ # prompt_yn QUESTION DEFAULT(y/n)
118
+ # Returns 0 for yes, 1 for no.
119
+ prompt_yn() {
120
+ local question="$1"
121
+ local default="${2:-y}"
122
+
123
+ if [[ "${CLAWSPARK_DEFAULTS}" == "true" ]]; then
124
+ [[ "${default}" == "y" ]] && return 0 || return 1
125
+ fi
126
+
127
+ local hint
128
+ if [[ "${default}" == "y" ]]; then hint="[Y/n]"; else hint="[y/N]"; fi
129
+
130
+ printf '\n%s%s %s%s ' "${BOLD}" "${question}" "${hint}" "${RESET}" >/dev/tty
131
+ local answer
132
+ read -r answer </dev/tty || answer=""
133
+ answer=$(to_lower "${answer}")
134
+
135
+ if [[ -z "${answer}" ]]; then
136
+ [[ "${default}" == "y" ]] && return 0 || return 1
137
+ fi
138
+ [[ "${answer}" =~ ^y(es)?$ ]] && return 0 || return 1
139
+ }
140
+
141
+ # ── check_command ───────────────────────────────────────────────────────────
142
+ # Returns 0 if the command exists on PATH, 1 otherwise.
143
+ check_command() {
144
+ command -v "$1" &>/dev/null
145
+ }
146
+
147
+ # ── Spinner ─────────────────────────────────────────────────────────────────
148
+ # spinner PID "message"
149
+ # Shows a spinner while a background process runs.
150
+ # Usage:
151
+ # long_running_command &
152
+ # spinner $! "Installing widgets..."
153
+ spinner() {
154
+ local pid="$1"
155
+ local msg="${2:-Working...}"
156
+ local frames=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
157
+ local frame_count=${#frames[@]}
158
+ local i=0
159
+
160
+ # Only show spinner if stdout is a terminal
161
+ if [[ ! -t 1 ]]; then
162
+ wait "${pid}" 2>/dev/null || true
163
+ return 0
164
+ fi
165
+
166
+ printf ' '
167
+ while kill -0 "${pid}" 2>/dev/null; do
168
+ printf '\r %s%s%s %s' "${CYAN}" "${frames[i % frame_count]}" "${RESET}" "${msg}"
169
+ i=$(( i + 1 ))
170
+ sleep 0.08
171
+ done
172
+
173
+ # Capture exit status of the background process
174
+ wait "${pid}" 2>/dev/null
175
+ local exit_code=$?
176
+
177
+ if [[ ${exit_code} -eq 0 ]]; then
178
+ printf '\r %s✓%s %s\n' "${GREEN}" "${RESET}" "${msg}"
179
+ else
180
+ printf '\r %s✗%s %s\n' "${RED}" "${RESET}" "${msg}"
181
+ fi
182
+ # Always return 0 so set -e does not abort the installer.
183
+ # Callers should validate success themselves (e.g. check_command).
184
+ return 0
185
+ }
186
+
187
+ # ── Horizontal rule ────────────────────────────────────────────────────────
188
+ hr() {
189
+ local cols
190
+ cols=$(tput cols 2>/dev/null || echo 60)
191
+ printf '%s%*s%s\n' "${BLUE}" "${cols}" '' "${RESET}" | tr ' ' '─'
192
+ }
193
+
194
+ # ── Box drawing ─────────────────────────────────────────────────────────────
195
+ # print_box "line1" "line2" ...
196
+ # Draws a bordered box around the given lines.
197
+ print_box() {
198
+ local lines=("$@")
199
+ local max_len=0
200
+ local line
201
+
202
+ for line in "${lines[@]}"; do
203
+ # Strip ANSI codes when measuring length
204
+ local stripped
205
+ stripped=$(printf '%s' "${line}" | sed 's/\x1b\[[0-9;]*m//g')
206
+ (( ${#stripped} > max_len )) && max_len=${#stripped}
207
+ done
208
+
209
+ local pad=$(( max_len + 2 ))
210
+ printf '%s┌%s┐%s\n' "${BLUE}" "$(printf '─%.0s' $(seq 1 "${pad}"))" "${RESET}"
211
+ for line in "${lines[@]}"; do
212
+ local stripped
213
+ stripped=$(printf '%s' "${line}" | sed 's/\x1b\[[0-9;]*m//g')
214
+ local spaces=$(( max_len - ${#stripped} ))
215
+ printf '%s│%s %s%*s %s│%s\n' "${BLUE}" "${RESET}" "${line}" "${spaces}" '' "${BLUE}" "${RESET}"
216
+ done
217
+ printf '%s└%s┘%s\n' "${BLUE}" "$(printf '─%.0s' $(seq 1 "${pad}"))" "${RESET}"
218
+ }
219
+
220
+ # ── Skills YAML parser ────────────────────────────────────────────────────
221
+ # _parse_enabled_skills FILE
222
+ # Prints one skill slug per line from the "enabled:" section.
223
+ # Handles both "- name: slug" and "- slug" formats.
224
+ _parse_enabled_skills() {
225
+ local skills_file="$1"
226
+ [[ -f "${skills_file}" && -r "${skills_file}" ]] || return 1
227
+ local in_enabled=false
228
+
229
+ while IFS= read -r line; do
230
+ [[ "${line}" =~ ^[[:space:]]*# ]] && continue
231
+ [[ -z "${line// }" ]] && continue
232
+
233
+ if [[ "${line}" =~ enabled:[[:space:]]*$ ]]; then
234
+ in_enabled=true; continue
235
+ fi
236
+ if ${in_enabled} && [[ "${line}" =~ ^[[:space:]]{0,3}[a-zA-Z] ]] && [[ ! "${line}" =~ ^[[:space:]]*- ]]; then
237
+ in_enabled=false; continue
238
+ fi
239
+ if ${in_enabled} && [[ "${line}" =~ ^[[:space:]]*-[[:space:]]+name:[[:space:]]+(.*) ]]; then
240
+ local slug="${BASH_REMATCH[1]}"; slug="${slug## }"; slug="${slug%% }"
241
+ echo "${slug}"; continue
242
+ fi
243
+ if ${in_enabled} && [[ "${line}" =~ ^[[:space:]]*-[[:space:]]+(.*) ]]; then
244
+ local slug="${BASH_REMATCH[1]}"; slug="${slug## }"; slug="${slug%% }"
245
+ [[ "${slug}" =~ ^[a-zA-Z]+: ]] && continue
246
+ echo "${slug}"
247
+ fi
248
+ done < "${skills_file}"
249
+ }
@@ -0,0 +1,156 @@
1
+ #!/usr/bin/env bash
2
+ # lib/detect-hardware.sh — Detects GPU, CPU, and memory for platform classification.
3
+ # Exports: HW_PLATFORM, HW_GPU_NAME, HW_GPU_VRAM_MB, HW_TOTAL_RAM_MB,
4
+ # HW_CPU_CORES, HW_CPU_ARCH, HW_DRIVER_VERSION
5
+ set -euo pipefail
6
+
7
+ detect_hardware() {
8
+ log_info "Detecting hardware..."
9
+
10
+ # ── CPU ─────────────────────────────────────────────────────────────────
11
+ HW_CPU_ARCH=$(uname -m)
12
+
13
+ if [[ -f /proc/cpuinfo ]]; then
14
+ HW_CPU_CORES=$(grep -c '^processor' /proc/cpuinfo 2>/dev/null || nproc 2>/dev/null || echo 1)
15
+ elif check_command sysctl; then
16
+ HW_CPU_CORES=$(sysctl -n hw.ncpu 2>/dev/null || echo 1)
17
+ else
18
+ HW_CPU_CORES=1
19
+ fi
20
+
21
+ # ── Memory ──────────────────────────────────────────────────────────────
22
+ if [[ -f /proc/meminfo ]]; then
23
+ local mem_kb
24
+ mem_kb=$(awk '/^MemTotal:/ {print $2}' /proc/meminfo 2>/dev/null || echo 0)
25
+ HW_TOTAL_RAM_MB=$(( mem_kb / 1024 ))
26
+ elif check_command sysctl; then
27
+ local mem_bytes
28
+ mem_bytes=$(sysctl -n hw.memsize 2>/dev/null || echo 0)
29
+ HW_TOTAL_RAM_MB=$(( mem_bytes / 1024 / 1024 ))
30
+ else
31
+ HW_TOTAL_RAM_MB=0
32
+ fi
33
+
34
+ # ── GPU / Platform detection ────────────────────────────────────────────
35
+ HW_GPU_NAME="none"
36
+ HW_GPU_VRAM_MB=0
37
+ HW_DRIVER_VERSION="n/a"
38
+ HW_PLATFORM="generic"
39
+
40
+ # Check for Jetson (Tegra) first — it may not have nvidia-smi
41
+ if [[ -f /etc/nv_tegra_release ]] || uname -r 2>/dev/null | grep -qi tegra; then
42
+ HW_PLATFORM="jetson"
43
+ HW_GPU_NAME="NVIDIA Jetson (Tegra)"
44
+ # Jetson shares system memory; VRAM = total RAM
45
+ HW_GPU_VRAM_MB="${HW_TOTAL_RAM_MB}"
46
+ log_info "Jetson platform detected via Tegra signature."
47
+ fi
48
+
49
+ # Check for DGX Spark via DMI product name
50
+ if [[ -f /sys/devices/virtual/dmi/id/product_name ]]; then
51
+ local product_name
52
+ product_name=$(cat /sys/devices/virtual/dmi/id/product_name 2>/dev/null || echo "")
53
+ if echo "${product_name}" | grep -qiE "DGX.Spark|DGX_Spark"; then
54
+ HW_PLATFORM="dgx-spark"
55
+ log_info "DGX Spark detected via DMI product name."
56
+ fi
57
+ fi
58
+
59
+ # nvidia-smi based detection
60
+ if check_command nvidia-smi; then
61
+ local gpu_info
62
+ gpu_info=$(nvidia-smi --query-gpu=name,memory.total,driver_version \
63
+ --format=csv,noheader,nounits 2>/dev/null || echo "")
64
+
65
+ if [[ -n "${gpu_info}" ]]; then
66
+ # Take the first GPU line
67
+ local first_gpu
68
+ first_gpu=$(echo "${gpu_info}" | head -n1)
69
+
70
+ HW_GPU_NAME=$(echo "${first_gpu}" | cut -d',' -f1 | xargs)
71
+ local vram_str
72
+ vram_str=$(echo "${first_gpu}" | cut -d',' -f2 | xargs)
73
+ # Handle [N/A] or "Not Supported" (DGX Spark unified memory)
74
+ if [[ "${vram_str}" =~ ^[0-9]+ ]]; then
75
+ HW_GPU_VRAM_MB="${vram_str%%.*}"
76
+ else
77
+ HW_GPU_VRAM_MB=0
78
+ fi
79
+ HW_DRIVER_VERSION=$(echo "${first_gpu}" | cut -d',' -f3 | xargs)
80
+
81
+ # Detect DGX Spark by GPU name (GB10 / Grace-Blackwell)
82
+ if echo "${HW_GPU_NAME}" | grep -qiE "GB10|DGX.*Spark|Grace.*Blackwell"; then
83
+ HW_PLATFORM="dgx-spark"
84
+ fi
85
+
86
+ # Detect RTX cards
87
+ if [[ "${HW_PLATFORM}" == "generic" ]]; then
88
+ if echo "${HW_GPU_NAME}" | grep -qiE "RTX|GeForce|Quadro"; then
89
+ HW_PLATFORM="rtx"
90
+ fi
91
+ fi
92
+ fi
93
+ fi
94
+
95
+ # macOS with Apple Silicon: detect GPU via system_profiler
96
+ if [[ "${HW_PLATFORM}" == "generic" && "$(uname)" == "Darwin" ]]; then
97
+ local chip_info
98
+ chip_info=$(sysctl -n machdep.cpu.brand_string 2>/dev/null || echo "")
99
+ if echo "${chip_info}" | grep -qi "Apple"; then
100
+ HW_PLATFORM="mac"
101
+ HW_GPU_NAME="Apple Silicon (${chip_info})"
102
+ # Apple Silicon uses unified memory; GPU VRAM = system RAM
103
+ HW_GPU_VRAM_MB="${HW_TOTAL_RAM_MB}"
104
+ HW_DRIVER_VERSION="Metal"
105
+ fi
106
+ fi
107
+
108
+ # Unified memory platforms: VRAM = system RAM (nvidia-smi reports N/A)
109
+ # This must come AFTER nvidia-smi parsing which may have reset VRAM to 0
110
+ if [[ "${HW_PLATFORM}" == "dgx-spark" ]]; then
111
+ HW_TOTAL_RAM_MB=131072 # 128 * 1024
112
+ HW_GPU_VRAM_MB=131072
113
+ elif [[ "${HW_PLATFORM}" == "jetson" && "${HW_GPU_VRAM_MB}" -eq 0 ]]; then
114
+ # Jetson uses unified memory; nvidia-smi returns N/A for VRAM
115
+ HW_GPU_VRAM_MB="${HW_TOTAL_RAM_MB}"
116
+ fi
117
+
118
+ # ── Validate NVIDIA driver version (Ollama needs >= 531 for GPU) ────────
119
+ if [[ "${HW_DRIVER_VERSION}" != "n/a" && "${HW_DRIVER_VERSION}" != "Metal" ]]; then
120
+ local driver_major
121
+ driver_major=$(echo "${HW_DRIVER_VERSION}" | cut -d. -f1)
122
+ if [[ "${driver_major}" =~ ^[0-9]+$ ]] && (( driver_major > 0 && driver_major < 531 )); then
123
+ log_warn "NVIDIA driver ${HW_DRIVER_VERSION} is too old for GPU inference (need >= 531)."
124
+ log_warn "Ollama will fall back to CPU-only mode. Update driver: sudo apt install nvidia-driver-535"
125
+ fi
126
+ fi
127
+
128
+ # ── Export globals ──────────────────────────────────────────────────────
129
+ export HW_PLATFORM HW_GPU_NAME HW_GPU_VRAM_MB HW_TOTAL_RAM_MB
130
+ export HW_CPU_CORES HW_CPU_ARCH HW_DRIVER_VERSION
131
+
132
+ # ── Pretty summary ──────────────────────────────────────────────────────
133
+ local ram_gb=$(( HW_TOTAL_RAM_MB / 1024 ))
134
+ local vram_gb=$(( HW_GPU_VRAM_MB / 1024 ))
135
+
136
+ local platform_label
137
+ case "${HW_PLATFORM}" in
138
+ dgx-spark) platform_label="NVIDIA DGX Spark" ;;
139
+ jetson) platform_label="NVIDIA Jetson" ;;
140
+ rtx) platform_label="NVIDIA RTX Desktop" ;;
141
+ mac) platform_label="macOS Apple Silicon" ;;
142
+ *) platform_label="Generic / Unknown GPU" ;;
143
+ esac
144
+
145
+ print_box \
146
+ "${BOLD}Hardware Summary${RESET}" \
147
+ "" \
148
+ "Platform : ${CYAN}${platform_label}${RESET}" \
149
+ "GPU : ${HW_GPU_NAME}" \
150
+ "VRAM : ${vram_gb} GB" \
151
+ "System RAM : ${ram_gb} GB" \
152
+ "CPU Cores : ${HW_CPU_CORES} (${HW_CPU_ARCH})" \
153
+ "Driver : ${HW_DRIVER_VERSION}"
154
+
155
+ log_success "Hardware detection complete — platform: ${HW_PLATFORM}"
156
+ }