@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
@@ -0,0 +1,242 @@
1
+ #!/usr/bin/env bash
2
+ # lib/setup-messaging.sh — Configures WhatsApp and/or Telegram messaging channels.
3
+ # Reads FLAG_MESSAGING (set by install.sh or interactive prompt).
4
+ set -euo pipefail
5
+
6
+ setup_messaging() {
7
+ log_info "Setting up messaging channels..."
8
+ hr
9
+
10
+ local messaging_choice="${FLAG_MESSAGING:-}"
11
+
12
+ # ── Prompt if not set via flag ──────────────────────────────────────────
13
+ if [[ -z "${messaging_choice}" ]]; then
14
+ local options=("WhatsApp" "Telegram" "Both" "Skip")
15
+ messaging_choice=$(prompt_choice "Which messaging channel(s) would you like?" options 0)
16
+ fi
17
+
18
+ messaging_choice=$(to_lower "${messaging_choice}")
19
+ export MESSAGING_CHOICE="${messaging_choice}"
20
+
21
+ case "${messaging_choice}" in
22
+ whatsapp)
23
+ _setup_whatsapp
24
+ ;;
25
+ telegram)
26
+ _setup_telegram
27
+ ;;
28
+ both)
29
+ _setup_whatsapp
30
+ _setup_telegram
31
+ ;;
32
+ skip)
33
+ log_info "Messaging setup skipped."
34
+ ;;
35
+ *)
36
+ log_warn "Unknown messaging option '${messaging_choice}' -- skipping."
37
+ ;;
38
+ esac
39
+
40
+ # Always start the gateway (Chat UI needs it even without messaging)
41
+ _start_gateway
42
+ }
43
+
44
+ # ── WhatsApp ────────────────────────────────────────────────────────────────
45
+
46
+ _setup_whatsapp() {
47
+ log_info "Configuring WhatsApp..."
48
+ printf '\n'
49
+ printf ' %s%sWhatsApp Setup%s\n' "${BOLD}" "${GREEN}" "${RESET}"
50
+ printf ' OpenClaw uses the Baileys library for WhatsApp Web linking.\n'
51
+ printf ' You will need to scan a QR code from your phone.\n'
52
+ printf ' Open WhatsApp on your phone > Linked Devices > Link a Device\n\n'
53
+ printf ' %s%sNote:%s WhatsApp linking depends on the upstream Baileys library.\n' "${BOLD}" "${YELLOW}" "${RESET}"
54
+ printf ' If linking fails, the Chat UI still works at:\n'
55
+ printf ' http://localhost:18789/__openclaw__/canvas/\n'
56
+ printf ' You can also use Telegram as an alternative messaging channel.\n\n'
57
+
58
+ if [[ "${CLAWSPARK_DEFAULTS}" == "true" ]]; then
59
+ log_warn "Cannot complete WhatsApp QR scan in --defaults mode."
60
+ log_info "Run 'openclaw channels login' later to link WhatsApp."
61
+ return 0
62
+ fi
63
+
64
+ # Ask for the user's WhatsApp phone number (for allowlist security)
65
+ printf ' Enter your WhatsApp phone number (with country code, e.g. 919878251239):\n'
66
+ printf ' > '
67
+ local wa_number=""
68
+ read -r wa_number </dev/tty || true
69
+ wa_number="${wa_number//[^0-9]/}" # strip non-digits
70
+
71
+ # Enable WhatsApp channel in config with security + message batching
72
+ openclaw config set channels.whatsapp.enabled true >> "${CLAWSPARK_LOG}" 2>&1 || true
73
+ openclaw config set channels.whatsapp.debounceMs 8000 >> "${CLAWSPARK_LOG}" 2>&1 || true
74
+ openclaw config set channels.whatsapp.groupPolicy disabled >> "${CLAWSPARK_LOG}" 2>&1 || true
75
+
76
+ # Set allowlist so only the owner can interact (no auto-replies to strangers)
77
+ if [[ -n "${wa_number}" ]]; then
78
+ openclaw config set channels.whatsapp.allowFrom "[\"${wa_number}@s.whatsapp.net\"]" >> "${CLAWSPARK_LOG}" 2>&1 || true
79
+ openclaw config set channels.whatsapp.dmPolicy allowlist >> "${CLAWSPARK_LOG}" 2>&1 || true
80
+ log_success "WhatsApp locked to your number: +${wa_number}"
81
+ else
82
+ log_warn "No phone number provided. Using pairing mode (strangers will get auto-replies)."
83
+ openclaw config set channels.whatsapp.dmPolicy pairing >> "${CLAWSPARK_LOG}" 2>&1 || true
84
+ fi
85
+
86
+ printf '\n'
87
+ printf ' Now scan the QR code with your phone:\n'
88
+ printf ' Open WhatsApp > Linked Devices > Link a Device\n\n'
89
+ printf ' Press Enter when ready...'
90
+ read -r </dev/tty || true
91
+
92
+ # Source Ollama env so the gateway can start if needed
93
+ local env_file="${HOME}/.openclaw/gateway.env"
94
+ if [[ -f "${env_file}" ]]; then set +e; set -a; source "${env_file}" 2>/dev/null; set +a; set -e; fi
95
+
96
+ # Use the channels login command for WhatsApp
97
+ openclaw channels login --channel whatsapp --verbose 2>&1 | tee -a "${CLAWSPARK_LOG}" || {
98
+ log_warn "WhatsApp linking exited with an error."
99
+ }
100
+
101
+ printf '\n'
102
+ if prompt_yn " Did you successfully link WhatsApp?" "y"; then
103
+ log_success "WhatsApp linked."
104
+ else
105
+ log_warn "WhatsApp not linked. You can try again later: openclaw channels login"
106
+ log_info "The Chat UI is always available at: http://localhost:18789/__openclaw__/canvas/"
107
+ fi
108
+ }
109
+
110
+ # ── Telegram ────────────────────────────────────────────────────────────────
111
+
112
+ _setup_telegram() {
113
+ log_info "Configuring Telegram..."
114
+ printf '\n'
115
+ printf ' %s%sTelegram Setup%s\n' "${BOLD}" "${GREEN}" "${RESET}"
116
+ printf ' The OpenClaw wizard will guide you through Telegram bot setup.\n'
117
+ printf ' You will need a bot token from @BotFather on Telegram.\n\n'
118
+
119
+ if [[ "${CLAWSPARK_DEFAULTS}" == "true" ]]; then
120
+ log_warn "Cannot configure Telegram bot in --defaults mode."
121
+ log_info "Run 'openclaw configure --section channels' later."
122
+ return 0
123
+ fi
124
+
125
+ # Source Ollama env
126
+ local env_file="${HOME}/.openclaw/gateway.env"
127
+ if [[ -f "${env_file}" ]]; then set +e; set -a; source "${env_file}" 2>/dev/null; set +a; set -e; fi
128
+
129
+ openclaw configure --section channels 2>&1 | tee -a "${CLAWSPARK_LOG}" || {
130
+ log_warn "Channel setup exited with an error. You can configure Telegram manually later."
131
+ return 0
132
+ }
133
+ log_success "Telegram bot configured."
134
+ }
135
+
136
+ # ── Gateway ─────────────────────────────────────────────────────────────────
137
+
138
+ _start_gateway() {
139
+ log_info "Starting OpenClaw gateway..."
140
+ local gateway_log="${CLAWSPARK_DIR}/gateway.log"
141
+ local gateway_pid_file="${CLAWSPARK_DIR}/gateway.pid"
142
+
143
+ # Kill existing gateway if running
144
+ if [[ -f "${gateway_pid_file}" ]]; then
145
+ local old_pid
146
+ old_pid=$(cat "${gateway_pid_file}")
147
+ if kill -0 "${old_pid}" 2>/dev/null; then
148
+ log_info "Stopping existing gateway (PID ${old_pid})..."
149
+ kill "${old_pid}" 2>/dev/null || true
150
+ sleep 1
151
+ fi
152
+ fi
153
+
154
+ # Source Ollama provider credentials
155
+ local env_file="${HOME}/.openclaw/gateway.env"
156
+ if [[ -f "${env_file}" ]]; then set +e; set -a; source "${env_file}" 2>/dev/null; set +a; set -e; fi
157
+
158
+ nohup openclaw gateway run --bind loopback > "${gateway_log}" 2>&1 &
159
+ local gw_pid=$!
160
+ echo "${gw_pid}" > "${gateway_pid_file}"
161
+
162
+ sleep 3
163
+ if kill -0 "${gw_pid}" 2>/dev/null; then
164
+ log_success "Gateway running (PID ${gw_pid}). Logs: ${gateway_log}"
165
+ else
166
+ log_warn "Gateway process exited unexpectedly. Check ${gateway_log}."
167
+ log_warn "You can start it manually later: clawspark restart"
168
+ return 0
169
+ fi
170
+
171
+ # Node host will be started later (after all config changes are done)
172
+ # to avoid gateway restart (1012) killing it mid-setup.
173
+ }
174
+
175
+ _start_node_host() {
176
+ log_info "Starting node host (agent execution engine)..."
177
+ local node_log="${CLAWSPARK_DIR}/node.log"
178
+ local node_pid_file="${CLAWSPARK_DIR}/node.pid"
179
+
180
+ # Ensure workspace directory exists and is writable
181
+ local workspace="${HOME}/workspace"
182
+ mkdir -p "${workspace}"
183
+ openclaw config set agents.defaults.workspace "${workspace}" >> "${CLAWSPARK_LOG}" 2>&1 || true
184
+
185
+ # Kill existing node host if running
186
+ if [[ -f "${node_pid_file}" ]]; then
187
+ local old_pid
188
+ old_pid=$(cat "${node_pid_file}")
189
+ kill "${old_pid}" 2>/dev/null || true
190
+ sleep 1
191
+ fi
192
+
193
+ local env_file="${HOME}/.openclaw/gateway.env"
194
+ if [[ -f "${env_file}" ]]; then set +e; set -a; source "${env_file}" 2>/dev/null; set +a; set -e; fi
195
+
196
+ nohup openclaw node run --host 127.0.0.1 --port 18789 > "${node_log}" 2>&1 &
197
+ local node_pid=$!
198
+ echo "${node_pid}" > "${node_pid_file}"
199
+
200
+ # Wait for the node to register and create a pairing request
201
+ sleep 5
202
+
203
+ # Auto-approve pending device requests (this is a local single-user install)
204
+ local attempt
205
+ for attempt in 1 2 3; do
206
+ local device_output
207
+ device_output=$(openclaw devices list 2>/dev/null || echo "")
208
+
209
+ # Only extract UUIDs from lines that contain "pending" or "Pending"
210
+ # to avoid approving already-paired devices or matching non-request UUIDs
211
+ local request_ids
212
+ request_ids=$(echo "${device_output}" | grep -iE 'pending|request' | grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' || true)
213
+ # Fallback: if no "pending" lines but there are UUIDs in a "Requests" section, try those
214
+ if [[ -z "${request_ids}" ]]; then
215
+ request_ids=$(echo "${device_output}" | sed -n '/^Request/,/^$/p' | grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' || true)
216
+ fi
217
+
218
+ if [[ -n "${request_ids}" ]]; then
219
+ local rid
220
+ for rid in ${request_ids}; do
221
+ openclaw devices approve "${rid}" >> "${CLAWSPARK_LOG}" 2>&1 && \
222
+ log_info "Auto-approved device: ${rid}" || true
223
+ done
224
+ # Restart node host after approval so it reconnects with proper auth
225
+ kill "${node_pid}" 2>/dev/null || true
226
+ sleep 2
227
+ nohup openclaw node run --host 127.0.0.1 --port 18789 > "${node_log}" 2>&1 &
228
+ node_pid=$!
229
+ echo "${node_pid}" > "${node_pid_file}"
230
+ sleep 3
231
+ break
232
+ fi
233
+ sleep 2
234
+ done
235
+
236
+ if kill -0 "${node_pid}" 2>/dev/null; then
237
+ log_success "Node host running (PID ${node_pid})."
238
+ else
239
+ log_warn "Node host failed to start. Agent will work without exec/browser tools."
240
+ log_warn "You can start it manually: openclaw node run --host 127.0.0.1 --port 18789"
241
+ fi
242
+ }
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env bash
2
+ # lib/setup-models.sh -- Multi-model configuration for OpenClaw.
3
+ # Configures vision and image generation model slots alongside the
4
+ # primary chat model that was already selected during install.
5
+ set -euo pipefail
6
+
7
+ setup_models() {
8
+ log_info "Configuring multi-model support..."
9
+
10
+ # The primary model is already set during install (SELECTED_MODEL_ID).
11
+ # Now configure additional model slots: vision and image generation.
12
+
13
+ # ── Vision model ──────────────────────────────────────────────────────
14
+ # Check for vision-capable models already pulled in Ollama
15
+ local vision_models=("qwen2.5vl" "qwen2.5-vl" "llava" "minicpm-v" "llama3.2-vision" "moondream")
16
+ local found_vision=""
17
+
18
+ for vm in "${vision_models[@]}"; do
19
+ if ollama list 2>/dev/null | grep -qi "${vm}"; then
20
+ found_vision="${vm}"
21
+ break
22
+ fi
23
+ done
24
+
25
+ if [[ -n "${found_vision}" ]]; then
26
+ # Get the full model tag from ollama list output
27
+ local full_tag
28
+ full_tag=$(ollama list 2>/dev/null | grep -i "${found_vision}" | head -1 | awk '{print $1}')
29
+ log_success "Found vision model: ${full_tag}"
30
+ openclaw config set agents.defaults.imageModel "ollama/${full_tag}" >> "${CLAWSPARK_LOG}" 2>&1 || true
31
+ else
32
+ # No vision model found -- decide whether to auto-pull based on VRAM
33
+ local vram_gb=$(( ${HW_GPU_VRAM_MB:-0} / 1024 ))
34
+ local skip_vision=false
35
+
36
+ # RTX with <=12GB VRAM: pulling a 5GB vision model alongside the chat
37
+ # model will cause OOM when both are loaded simultaneously
38
+ if [[ "${HW_PLATFORM:-}" == "rtx" ]] && (( vram_gb > 0 && vram_gb <= 12 )); then
39
+ skip_vision=true
40
+ log_info "Skipping vision model auto-pull (${vram_gb}GB VRAM -- dual-model loading would OOM)."
41
+ log_info "Add one later when needed: ollama pull moondream (1.5GB, fits alongside chat model)"
42
+ fi
43
+
44
+ if [[ "${skip_vision}" != "true" ]]; then
45
+ local vision_choice="qwen2.5vl:7b"
46
+ log_info "No vision model found. Pulling ${vision_choice} for image analysis (~5GB)..."
47
+ (ollama pull "${vision_choice}") >> "${CLAWSPARK_LOG}" 2>&1 &
48
+ spinner $! "Pulling ${vision_choice}..."
49
+ # Wait a moment for Ollama to index the model, then check with retries
50
+ local _vision_ok=false
51
+ local _retry
52
+ for _retry in 1 2 3; do
53
+ if ollama list 2>/dev/null | grep -qi "qwen2.5vl"; then
54
+ _vision_ok=true
55
+ break
56
+ fi
57
+ sleep 2
58
+ done
59
+ if [[ "${_vision_ok}" == "true" ]]; then
60
+ found_vision="qwen2.5vl"
61
+ openclaw config set agents.defaults.imageModel "ollama/${vision_choice}" >> "${CLAWSPARK_LOG}" 2>&1 || true
62
+ log_success "Vision model configured: ollama/${vision_choice}"
63
+ else
64
+ log_warn "Vision model pull failed. You can add one later: ollama pull qwen2.5vl:7b"
65
+ fi
66
+ fi
67
+ fi
68
+
69
+ # ── Register vision model with explicit input modality ─────────────────
70
+ # OpenClaw discovers Ollama models via /v1/models which doesn't report
71
+ # vision capability. We must explicitly register the model with
72
+ # input: ["text", "image"] so the image tool works.
73
+ local config_file="${HOME}/.openclaw/openclaw.json"
74
+ if [[ -n "${found_vision}" && -f "${config_file}" ]]; then
75
+ local vision_model_id="${found_vision}"
76
+ # Get the full tag
77
+ local vision_full_tag
78
+ vision_full_tag=$(ollama list 2>/dev/null | grep -i "${vision_model_id}" | head -1 | awk '{print $1}')
79
+ if [[ -n "${vision_full_tag}" ]]; then
80
+ python3 -c "
81
+ import json, sys
82
+ path = sys.argv[1]
83
+ model_id = sys.argv[2]
84
+ with open(path) as f:
85
+ cfg = json.load(f)
86
+ cfg.setdefault('models', {}).setdefault('providers', {}).setdefault('ollama', {})
87
+ cfg['models']['providers']['ollama'].setdefault('baseUrl', 'http://127.0.0.1:11434/v1')
88
+ # Use openai-completions api -- Ollama's /v1 endpoint is OpenAI-compatible
89
+ # and the built-in openai-completions provider is always registered,
90
+ # unlike the dynamic 'ollama' api which is missing from the vision code path.
91
+ cfg['models']['providers']['ollama']['api'] = 'openai-completions'
92
+ cfg['models']['providers']['ollama']['models'] = [
93
+ {
94
+ 'id': model_id,
95
+ 'name': model_id.replace(':', ' ').title(),
96
+ 'api': 'openai-completions',
97
+ 'input': ['text', 'image'],
98
+ 'contextWindow': 32768,
99
+ 'maxTokens': 8192
100
+ }
101
+ ]
102
+ with open(path, 'w') as f:
103
+ json.dump(cfg, f, indent=2)
104
+ print('ok')
105
+ " "${config_file}" "${vision_full_tag}" 2>> "${CLAWSPARK_LOG}" || {
106
+ log_warn "Could not register vision model modality."
107
+ }
108
+ log_success "Vision model registered with image input capability."
109
+ fi
110
+ fi
111
+
112
+ # ── Image generation model ────────────────────────────────────────────
113
+ # Image generation (text-to-image) is optional and more complex.
114
+ # It typically requires ComfyUI, Stable Diffusion, or an external API.
115
+ # For now, log a message about how to enable it later.
116
+ log_info "Image generation: not configured (optional)."
117
+ log_info " To enable later, set up ComfyUI or a text-to-image API and run:"
118
+ log_info " openclaw config set agents.defaults.imageGenerationModel <provider>/<model>"
119
+
120
+ log_success "Model configuration complete."
121
+ }