karnel-termux 4.17.21 → 4.17.23

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 (48) hide show
  1. package/README.md +5 -4
  2. package/docs/CHANGELOG.md +8 -0
  3. package/install.sh +20 -5
  4. package/karnel/RELEASE_COMMIT +1 -1
  5. package/karnel/cli/commands/agent.sh +9 -5
  6. package/karnel/cli/commands/brain.sh +18 -14
  7. package/karnel/cli/commands/doctor/fixes.sh +4 -4
  8. package/karnel/cli/commands/doctor.sh +4 -2
  9. package/karnel/cli/commands/ia.sh +5 -1
  10. package/karnel/cli/commands/pg.sh +5 -2
  11. package/karnel/cli/commands/restore.sh +3 -0
  12. package/karnel/cli/commands/update.sh +18 -0
  13. package/karnel/cli/commands/upgrade.sh +9 -2
  14. package/karnel/cli/commands/voice.sh +4 -2
  15. package/karnel/modules/voice.sh +8 -5
  16. package/karnel/tools/ai/codebuff/install.sh +69 -9
  17. package/karnel/tools/ai/codex/install.sh +3 -0
  18. package/karnel/tools/ai/gemini-cli/install.sh +3 -0
  19. package/karnel/tools/ai/kimi-code/install.sh +3 -0
  20. package/karnel/tools/ai/minimax-cli/install.sh +3 -0
  21. package/karnel/tools/ai/openclaude/install.sh +3 -0
  22. package/karnel/tools/ai/openclaw/install.sh +3 -0
  23. package/karnel/tools/ai/pi/install.sh +3 -0
  24. package/karnel/tools/ai/qoder/install.sh +140 -29
  25. package/karnel/tools/ai/qwen-code/install.sh +3 -0
  26. package/karnel/tools/deploy/netlify/install.sh +10 -3
  27. package/karnel/tools/deploy/vercel/install.sh +10 -3
  28. package/karnel/tools/lang/bun/install.sh +2 -2
  29. package/karnel/tools/npm/all.sh +1 -23
  30. package/karnel/tools/npm/live-server/install.sh +2 -0
  31. package/karnel/tools/npm/localtunnel/install.sh +3 -1
  32. package/karnel/tools/npm/markserv/install.sh +2 -0
  33. package/karnel/tools/npm/ncu/install.sh +2 -0
  34. package/karnel/tools/npm/nestjs/install.sh +2 -0
  35. package/karnel/tools/npm/ngrok/install.sh +2 -0
  36. package/karnel/tools/npm/prettier/install.sh +2 -0
  37. package/karnel/tools/npm/psqlformat/install.sh +2 -0
  38. package/karnel/tools/npm/typescript/install.sh +2 -0
  39. package/karnel/tools/npm/vercel/install.sh +2 -0
  40. package/karnel/tools/utils/filecheck/filecheck.py +1 -0
  41. package/karnel/tools/utils/qrcode/qrcode.py +1 -0
  42. package/karnel/tools/utils/websites/websites.py +1 -0
  43. package/karnel/tools/voice/uninstall.sh +1 -0
  44. package/karnel/utils/agent_actions.sh +8 -0
  45. package/karnel/utils/agent_llm.sh +7 -7
  46. package/karnel/utils/downloaded-python.sh +1 -1
  47. package/karnel/utils/npm-shebang.sh +30 -0
  48. package/package.json +1 -1
@@ -2,6 +2,7 @@
2
2
 
3
3
  import "@/utils/log"
4
4
  import "@/utils/version"
5
+ import "@/utils/npm-shebang"
5
6
 
6
7
  LOG_FILE="$KARNEL_CACHE/install_ai.log"
7
8
 
@@ -39,6 +40,7 @@ _install_minimax_cli_npm_impl() {
39
40
  log_error "Failed to install MiniMax CLI"
40
41
  return 1
41
42
  fi
43
+ _fix_npm_shebang "mmx"
42
44
 
43
45
  return 0
44
46
  }
@@ -92,6 +94,7 @@ _update_minimax_cli_impl() {
92
94
  log_error "Failed to update MiniMax CLI"
93
95
  return 1
94
96
  fi
97
+ _fix_npm_shebang "mmx"
95
98
  return 0
96
99
  }
97
100
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  import "@/utils/log"
4
4
  import "@/utils/version"
5
+ import "@/utils/npm-shebang"
5
6
 
6
7
  LOG_FILE="$KARNEL_CACHE/install_ai.log"
7
8
 
@@ -42,6 +43,7 @@ _install_openclaude_npm_impl() {
42
43
  log_error "Failed to install OpenClaude"
43
44
  return 1
44
45
  fi
46
+ _fix_npm_shebang "openclaude"
45
47
 
46
48
  return 0
47
49
  }
@@ -96,6 +98,7 @@ _update_openclaude_impl() {
96
98
  log_error "Failed to update OpenClaude"
97
99
  return 1
98
100
  fi
101
+ _fix_npm_shebang "openclaude"
99
102
  return 0
100
103
  }
101
104
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  import "@/utils/log"
4
4
  import "@/utils/version"
5
+ import "@/utils/npm-shebang"
5
6
 
6
7
  LOG_FILE="$KARNEL_CACHE/install_ai.log"
7
8
 
@@ -47,6 +48,7 @@ _install_openclaw_npm_impl() {
47
48
  log_error "Failed to install OpenClaw"
48
49
  return 1
49
50
  fi
51
+ _fix_npm_shebang "openclaw"
50
52
 
51
53
  return 0
52
54
  }
@@ -101,6 +103,7 @@ _update_openclaw_impl() {
101
103
  log_error "Failed to update OpenClaw"
102
104
  return 1
103
105
  fi
106
+ _fix_npm_shebang "openclaw"
104
107
  return 0
105
108
  }
106
109
 
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env bash
2
2
  import "@/utils/log"
3
3
  import "@/utils/version"
4
+ import "@/utils/npm-shebang"
4
5
 
5
6
  LOG_FILE="$KARNEL_CACHE/install_ai.log"
6
7
 
@@ -39,6 +40,7 @@ _install_pi_npm_impl() {
39
40
  log_error "Failed to install Pi"
40
41
  return 1
41
42
  fi
43
+ _fix_npm_shebang "pi"
42
44
 
43
45
  return 0
44
46
  }
@@ -90,6 +92,7 @@ _update_pi_impl() {
90
92
  log_error "Failed to update Pi"
91
93
  return 1
92
94
  fi
95
+ _fix_npm_shebang "pi"
93
96
  return 0
94
97
  }
95
98
 
@@ -11,6 +11,8 @@ QODER_MANIFEST_URL="https://qoder-ide.oss-accelerate.aliyuncs.com/qodercli/chann
11
11
  QODER_MARKER=".karnel-managed"
12
12
  QODER_WRAPPER_MARKER="$QODER_DATA_DIR/.karnel-wrapper"
13
13
  QODER_PROOT_MARKER="$PREFIX/share/karnel-installers/qoder"
14
+ QODER_PREVIOUS_DATA=""
15
+ QODER_STAGED_WRAPPER=""
14
16
 
15
17
  _qoder_detect_ubuntu_root() {
16
18
  local root
@@ -153,14 +155,44 @@ _download_qoder_binary_impl() {
153
155
  fi
154
156
 
155
157
  chmod +x "$staging_dir/qodercli"
156
- replace_managed_directory "$staging_dir" "$QODER_DATA_DIR" "$QODER_MARKER"
158
+ if ! _activate_qoder_payload "$staging_dir"; then
159
+ rm -rf "$staging_dir"
160
+ return 1
161
+ fi
157
162
  }
158
163
 
159
- _compile_qoder_helper() {
160
- loading "Compiling helper" _compile_qoder_helper_impl
164
+ _activate_qoder_payload() {
165
+ local staging_dir="$1" backup=""
166
+ printf '%s\n' 'karnel-managed-v1' >"$staging_dir/$QODER_MARKER" || return 1
167
+ if [[ -e "$QODER_DATA_DIR" ]]; then
168
+ if [[ ! -f "$QODER_DATA_DIR/$QODER_MARKER" ]]; then
169
+ log_error "Refusing to replace unowned installation: $QODER_DATA_DIR"
170
+ return 1
171
+ fi
172
+ backup=$(mktemp -d "$(dirname "$QODER_DATA_DIR")/.qoder-previous.XXXXXX") || return 1
173
+ rmdir "$backup" || return 1
174
+ mv "$QODER_DATA_DIR" "$backup" || return 1
175
+ fi
176
+ if ! mv "$staging_dir" "$QODER_DATA_DIR"; then
177
+ [[ -z "$backup" ]] || mv "$backup" "$QODER_DATA_DIR"
178
+ return 1
179
+ fi
180
+ if [[ -n "$backup" && -f "$backup/.karnel-wrapper" ]] &&
181
+ ! cp "$backup/.karnel-wrapper" "$QODER_WRAPPER_MARKER"; then
182
+ rm -rf "$QODER_DATA_DIR"
183
+ mv "$backup" "$QODER_DATA_DIR"
184
+ return 1
185
+ fi
186
+ QODER_PREVIOUS_DATA="$backup"
187
+ }
188
+
189
+ _restore_qoder_payload() {
190
+ rm -rf "$QODER_DATA_DIR"
191
+ [[ -z "$QODER_PREVIOUS_DATA" ]] || mv "$QODER_PREVIOUS_DATA" "$QODER_DATA_DIR"
192
+ QODER_PREVIOUS_DATA=""
161
193
  }
162
194
 
163
- _compile_qoder_helper_impl() {
195
+ _stage_qoder_helper() {
164
196
  local HELPER_SRC="$KARNEL_PATH/tools/ai/qoder/helper/qoder_helper.c"
165
197
  if [ ! -f "$HELPER_SRC" ]; then
166
198
  log_error "Helper source not found at $HELPER_SRC"
@@ -168,22 +200,50 @@ _compile_qoder_helper_impl() {
168
200
  fi
169
201
 
170
202
  local staged_wrapper
203
+ if [[ -e "$PREFIX/bin/qodercli" || -L "$PREFIX/bin/qodercli" ]] &&
204
+ ! installer_file_owned "$PREFIX/bin/qodercli" "$QODER_WRAPPER_MARKER"; then
205
+ log_error "Refusing to replace an existing Qoder wrapper not owned by Karnel"
206
+ return 1
207
+ fi
171
208
  staged_wrapper=$(mktemp "$PREFIX/bin/.qodercli.XXXXXX") || return 1
172
209
  if ! cc -O2 -o "$staged_wrapper" "$HELPER_SRC" &>>"$LOG_FILE"; then
173
210
  rm -f "$staged_wrapper"
174
211
  log_error "Failed to compile qoder helper"
175
212
  return 1
176
213
  fi
214
+ chmod +x "$staged_wrapper" || { rm -f "$staged_wrapper"; return 1; }
215
+ QODER_STAGED_WRAPPER="$staged_wrapper"
216
+ }
177
217
 
178
- chmod +x "$staged_wrapper"
179
- mv "$staged_wrapper" "$PREFIX/bin/qodercli" || return 1
180
- record_managed_file "$PREFIX/bin/qodercli" "$QODER_WRAPPER_MARKER"
218
+ _activate_qoder_wrapper() {
219
+ activate_installer_file "$QODER_STAGED_WRAPPER" "$PREFIX/bin/qodercli" "$QODER_WRAPPER_MARKER"
220
+ }
221
+
222
+ _compile_qoder_helper() {
223
+ loading "Compiling helper" _stage_qoder_helper || return 1
224
+ if ! _activate_qoder_wrapper; then
225
+ rm -f "$QODER_STAGED_WRAPPER"
226
+ return 1
227
+ fi
228
+ QODER_STAGED_WRAPPER=""
181
229
  }
182
230
 
183
231
  _install_qoder_native() {
232
+ QODER_PREVIOUS_DATA="" QODER_STAGED_WRAPPER=""
184
233
  _qoder_install_deps_native || return 1
185
- _download_qoder_binary || return 1
186
- _compile_qoder_helper || return 1
234
+ loading "Compiling helper" _stage_qoder_helper || return 1
235
+ if ! _download_qoder_binary; then
236
+ rm -f "$QODER_STAGED_WRAPPER"
237
+ return 1
238
+ fi
239
+ if ! _activate_qoder_wrapper; then
240
+ rm -f "$QODER_STAGED_WRAPPER"
241
+ _restore_qoder_payload
242
+ return 1
243
+ fi
244
+ QODER_STAGED_WRAPPER=""
245
+ [[ -z "$QODER_PREVIOUS_DATA" ]] || rm -rf "$QODER_PREVIOUS_DATA"
246
+ QODER_PREVIOUS_DATA=""
187
247
  log_success "Qoder installed natively"
188
248
  return 0
189
249
  }
@@ -192,6 +252,27 @@ _install_qoder_proot() {
192
252
  loading "Installing Qoder (proot-distro)" _install_qoder_proot_impl
193
253
  }
194
254
 
255
+ _stage_qoder_proot_wrapper() {
256
+ local ubuntu_root="$1" qoder_dir="$2" wrapper_src="$KARNEL_PATH/tools/ai/qoder/bin/qodercli"
257
+ if [[ -e "$PREFIX/bin/qodercli" || -L "$PREFIX/bin/qodercli" ]] &&
258
+ ! installer_file_owned "$PREFIX/bin/qodercli" "$QODER_PROOT_MARKER"; then
259
+ log_error "Refusing to replace an existing Qoder wrapper not owned by Karnel"
260
+ return 1
261
+ fi
262
+ [ -f "$wrapper_src" ] || { log_error "Wrapper template not found at $wrapper_src"; return 1; }
263
+ QODER_STAGED_WRAPPER=$(mktemp "$PREFIX/bin/.qodercli.XXXXXX") || return 1
264
+ if ! sed -e "s|__UBUNTU_ROOTFS__|$ubuntu_root|g" -e "s|__QODER_DIR__|$qoder_dir|g" \
265
+ "$wrapper_src" >"$QODER_STAGED_WRAPPER" || ! chmod +x "$QODER_STAGED_WRAPPER"; then
266
+ rm -f "$QODER_STAGED_WRAPPER"
267
+ QODER_STAGED_WRAPPER=""
268
+ return 1
269
+ fi
270
+ }
271
+
272
+ _activate_qoder_proot_wrapper() {
273
+ activate_installer_file "$QODER_STAGED_WRAPPER" "$PREFIX/bin/qodercli" "$QODER_PROOT_MARKER"
274
+ }
275
+
195
276
  _install_qoder_proot_impl() {
196
277
  case "$(uname -m)" in
197
278
  aarch64|arm64) ;;
@@ -200,16 +281,25 @@ _install_qoder_proot_impl() {
200
281
  mkdir -p "$(dirname "$LOG_FILE")"
201
282
 
202
283
  if ! command -v proot-distro &>/dev/null; then
203
- yes | pkg install proot-distro &>>"$LOG_FILE"
284
+ if ! yes | pkg install proot-distro &>>"$LOG_FILE"; then
285
+ log_error "Failed to install proot-distro"
286
+ return 1
287
+ fi
204
288
  fi
205
289
 
206
290
  if [ ! -d "$(_qoder_detect_ubuntu_root)" ]; then
207
- proot-distro install ubuntu:24.04 &>>"$LOG_FILE"
291
+ if ! proot-distro install ubuntu:24.04 &>>"$LOG_FILE"; then
292
+ log_error "Failed to install Ubuntu Proot"
293
+ return 1
294
+ fi
208
295
  fi
209
296
 
210
- _qoder_proot_ubuntu /bin/bash -c \
297
+ if ! _qoder_proot_ubuntu /bin/bash -c \
211
298
  'apt-get update && apt-get upgrade -y && apt-get install -y curl ca-certificates' \
212
- &>>"$LOG_FILE"
299
+ &>>"$LOG_FILE"; then
300
+ log_error "Failed to prepare Ubuntu Proot"
301
+ return 1
302
+ fi
213
303
 
214
304
  local download_url
215
305
  download_url=$(_get_qoder_download_url "arm64")
@@ -230,45 +320,54 @@ _install_qoder_proot_impl() {
230
320
  log_error "Refusing to replace Qoder Proot data not owned by Karnel"
231
321
  return 1
232
322
  fi
233
- mkdir -p "$qoder_dir"
323
+ if ! _stage_qoder_proot_wrapper "$ubuntu_root" "$qoder_dir"; then
324
+ return 1
325
+ fi
326
+ mkdir -p "$qoder_dir" || { rm -f "$QODER_STAGED_WRAPPER"; return 1; }
234
327
 
235
328
  local archive_filename
236
329
  archive_filename=$(basename "$download_url")
237
330
 
238
331
  if ! curl -fsSL "$download_url" -o "$qoder_dir/$archive_filename" &>>"$LOG_FILE"; then
332
+ rm -rf "$qoder_dir"
333
+ rm -f "$QODER_STAGED_WRAPPER"
239
334
  log_error "Failed to download Qoder binary"
240
335
  return 1
241
336
  fi
242
337
 
243
338
  local expected actual
244
339
  expected=$(_get_qoder_download_sha256 arm64)
245
- actual=$(sha256sum "$qoder_dir/$archive_filename" 2>>"$LOG_FILE") || return 1
340
+ actual=$(sha256sum "$qoder_dir/$archive_filename" 2>>"$LOG_FILE") || { rm -rf "$qoder_dir" "$QODER_STAGED_WRAPPER"; return 1; }
246
341
  if [[ ! "$expected" =~ ^[0-9a-f]{64}$ || "${actual%% *}" != "$expected" ]]; then
247
- rm -f "$qoder_dir/$archive_filename"
342
+ rm -rf "$qoder_dir"
343
+ rm -f "$QODER_STAGED_WRAPPER"
248
344
  log_error "Qoder archive has no valid matching SHA-256 in the official manifest"
249
345
  return 1
250
346
  fi
251
347
  if ! extract_tarball "$qoder_dir/$archive_filename" "$qoder_dir"; then
348
+ rm -rf "$qoder_dir"
349
+ rm -f "$QODER_STAGED_WRAPPER"
252
350
  return 1
253
351
  fi
254
352
 
255
353
  if [ ! -f "$qoder_dir/qodercli" ]; then
354
+ rm -rf "$qoder_dir"
355
+ rm -f "$QODER_STAGED_WRAPPER"
256
356
  log_error "Qoder binary not found after extraction"
257
357
  return 1
258
358
  fi
259
359
 
260
- chmod +x "$qoder_dir/qodercli"
261
- printf '%s\n' 'karnel-managed-v1' >"$qoder_dir/.karnel-managed"
262
-
263
- local wrapper_src="$KARNEL_PATH/tools/ai/qoder/bin/qodercli"
264
- if [ ! -f "$wrapper_src" ]; then
265
- log_error "Wrapper template not found at $wrapper_src"
360
+ if ! chmod +x "$qoder_dir/qodercli" || ! printf '%s\n' 'karnel-managed-v1' >"$qoder_dir/.karnel-managed"; then
361
+ rm -rf "$qoder_dir"
362
+ rm -f "$QODER_STAGED_WRAPPER"
363
+ return 1
364
+ fi
365
+ if ! _activate_qoder_proot_wrapper; then
366
+ rm -f "$QODER_STAGED_WRAPPER"
367
+ rm -rf "$qoder_dir"
266
368
  return 1
267
369
  fi
268
- sed -e "s|__UBUNTU_ROOTFS__|$ubuntu_root|g" -e "s|__QODER_DIR__|$qoder_dir|g" \
269
- "$wrapper_src" >"$PREFIX/bin/qodercli"
270
- chmod +x "$PREFIX/bin/qodercli"
271
- record_managed_file "$PREFIX/bin/qodercli" "$QODER_PROOT_MARKER" || return 1
370
+ QODER_STAGED_WRAPPER=""
272
371
 
273
372
  return 0
274
373
  }
@@ -409,14 +508,26 @@ _update_qoder_proot_impl() {
409
508
  return 1
410
509
  fi
411
510
 
412
- chmod +x "$staging_dir/qodercli"
413
- printf '%s\n' 'karnel-managed-v1' >"$staging_dir/.karnel-managed"
414
- old_dir="${qoder_dir}.previous.$$"
511
+ if ! chmod +x "$staging_dir/qodercli" || ! printf '%s\n' 'karnel-managed-v1' >"$staging_dir/.karnel-managed" ||
512
+ ! _stage_qoder_proot_wrapper "$ubuntu_root" "$qoder_dir"; then
513
+ rm -rf "$staging_dir"
514
+ return 1
515
+ fi
516
+ old_dir=$(mktemp -d "$(dirname "$qoder_dir")/.qoder-previous.XXXXXX") || { rm -f "$QODER_STAGED_WRAPPER"; return 1; }
517
+ rmdir "$old_dir" || { rm -f "$QODER_STAGED_WRAPPER"; return 1; }
415
518
  if ! mv "$qoder_dir" "$old_dir" || ! mv "$staging_dir" "$qoder_dir"; then
416
519
  [[ ! -d "$old_dir" ]] || mv "$old_dir" "$qoder_dir"
417
520
  rm -rf "$staging_dir"
521
+ rm -f "$QODER_STAGED_WRAPPER"
522
+ return 1
523
+ fi
524
+ if ! _activate_qoder_proot_wrapper; then
525
+ rm -f "$QODER_STAGED_WRAPPER"
526
+ rm -rf "$qoder_dir"
527
+ mv "$old_dir" "$qoder_dir"
418
528
  return 1
419
529
  fi
530
+ QODER_STAGED_WRAPPER=""
420
531
  rm -rf "$old_dir"
421
532
 
422
533
  log_success "Qoder (proot-distro) updated"
@@ -2,6 +2,7 @@
2
2
 
3
3
  import "@/utils/log"
4
4
  import "@/utils/version"
5
+ import "@/utils/npm-shebang"
5
6
 
6
7
  LOG_FILE="$KARNEL_CACHE/install_ai.log"
7
8
 
@@ -42,6 +43,7 @@ _install_qwen_code_npm_impl() {
42
43
  log_error "Failed to install Qwen Code"
43
44
  return 1
44
45
  fi
46
+ _fix_npm_shebang "qwen"
45
47
 
46
48
  return 0
47
49
  }
@@ -97,6 +99,7 @@ _update_qwen_code_impl() {
97
99
  log_error "Failed to update Qwen Code"
98
100
  return 1
99
101
  fi
102
+ _fix_npm_shebang "qwen"
100
103
  return 0
101
104
  }
102
105
 
@@ -9,7 +9,9 @@ NETLIFY_VERSION="27.1.1"
9
9
  NETLIFY_MARKER="$PREFIX/share/karnel-installers/netlify"
10
10
 
11
11
  _netlify_is_owned() {
12
- command -v netlify &>/dev/null && [[ -f "$NETLIFY_MARKER" ]] || return 1
12
+ local binary
13
+ binary=$(command -v netlify) || return 1
14
+ managed_file_matches "$binary" "$NETLIFY_MARKER"
13
15
  }
14
16
 
15
17
  _netlify_node_supported() {
@@ -43,12 +45,17 @@ install_netlify() {
43
45
  log_error "Failed to install Netlify CLI (see $LOG_FILE)"
44
46
  return 1
45
47
  fi
46
- command -v termux-fix-shebang &>/dev/null && termux-fix-shebang "$(command -v netlify)" &>/dev/null
48
+ local binary
49
+ binary=$(command -v netlify) || { log_error "Netlify CLI was not found after installation"; return 1; }
50
+ command -v termux-fix-shebang &>/dev/null && termux-fix-shebang "$binary" &>/dev/null
47
51
  if ! netlify --version &>/dev/null; then
48
52
  log_error "Netlify CLI did not start after installation"
49
53
  return 1
50
54
  fi
51
- mkdir -p "$(dirname "$NETLIFY_MARKER")" && : >"$NETLIFY_MARKER"
55
+ if ! record_managed_file "$binary" "$NETLIFY_MARKER"; then
56
+ log_error "Failed to record Netlify CLI ownership"
57
+ return 1
58
+ fi
52
59
  log_success "Netlify CLI installed"
53
60
  }
54
61
 
@@ -8,7 +8,9 @@ LOG_FILE="${LOG_FILE:-${KARNEL_CACHE:-$HOME/.cache/karnel}/install_deploy.log}"
8
8
  VERCEL_MARKER="$PREFIX/share/karnel-installers/vercel"
9
9
 
10
10
  _vercel_is_owned() {
11
- command -v vercel &>/dev/null && [[ -f "$VERCEL_MARKER" ]] || return 1
11
+ local binary
12
+ binary=$(command -v vercel) || return 1
13
+ managed_file_matches "$binary" "$VERCEL_MARKER"
12
14
  }
13
15
 
14
16
  install_vercel() {
@@ -29,8 +31,13 @@ install_vercel() {
29
31
  log_error "Failed to install Vercel CLI (see $LOG_FILE)"
30
32
  return 1
31
33
  fi
32
- command -v termux-fix-shebang &>/dev/null && termux-fix-shebang "$(command -v vercel)" &>/dev/null
33
- mkdir -p "$(dirname "$VERCEL_MARKER")" && : >"$VERCEL_MARKER"
34
+ local binary
35
+ binary=$(command -v vercel) || { log_error "Vercel CLI was not found after installation"; return 1; }
36
+ command -v termux-fix-shebang &>/dev/null && termux-fix-shebang "$binary" &>/dev/null
37
+ if ! record_managed_file "$binary" "$VERCEL_MARKER"; then
38
+ log_error "Failed to record Vercel CLI ownership"
39
+ return 1
40
+ fi
34
41
  log_success "Vercel CLI installed"
35
42
  }
36
43
 
@@ -294,7 +294,7 @@ _install_bun_proot_impl() {
294
294
  cd /tmp &&
295
295
  curl -fsSL "$1" -o bun.zip &&
296
296
  [ "$(sha256sum bun.zip | awk "{print \$1}")" = "$2" ] &&
297
- unzip -l bun.zip | awk "NR>3{print \$NF}" | grep -Eq "(\\.\\./|^\\.\\./|^/)" && { echo "Refusing Bun archive with unsafe paths" >&2; exit 1; } &&
297
+ if unzip -l bun.zip | awk "NR>3{print \$NF}" | grep -Eq "(\\.\\./|^\\.\\./|^/)"; then echo "Refusing Bun archive with unsafe paths" >&2; exit 1; fi &&
298
298
  unzip -o bun.zip >/dev/null 2>&1 &&
299
299
  mkdir -p /usr/local/bin &&
300
300
  mv bun-linux-aarch64/bun /usr/local/bin/bun &&
@@ -408,7 +408,7 @@ _update_bun_proot() {
408
408
  cd /tmp &&
409
409
  curl -fsSL "$1" -o bun.zip &&
410
410
  [ "$(sha256sum bun.zip | awk "{print \$1}")" = "$2" ] &&
411
- unzip -l bun.zip | awk "NR>3{print \$NF}" | grep -Eq "(\\.\\./|^\\.\\./|^/)" && { echo "Refusing Bun archive with unsafe paths" >&2; exit 1; } &&
411
+ if unzip -l bun.zip | awk "NR>3{print \$NF}" | grep -Eq "(\\.\\./|^\\.\\./|^/)"; then echo "Refusing Bun archive with unsafe paths" >&2; exit 1; fi &&
412
412
  unzip -o bun.zip >/dev/null 2>&1 &&
413
413
  mkdir -p /usr/local/bin &&
414
414
  mv bun-linux-aarch64/bun /usr/local/bin/bun &&
@@ -26,29 +26,7 @@ done
26
26
  unset _tool
27
27
  _register_safe_reinstall_handlers npm "${NODE_PACKAGES[@]}"
28
28
 
29
- _fix_npm_shebang() {
30
- local bin_name="$1"
31
- local bin_path="$PREFIX/bin/$bin_name"
32
- [ ! -f "$bin_path" ] && [ ! -L "$bin_path" ] && return 0
33
-
34
- local real_path
35
- real_path=$(readlink -f "$bin_path" 2>/dev/null || echo "$bin_path")
36
- [ ! -f "$real_path" ] && return 0
37
-
38
- local shebang
39
- shebang=$(head -1 "$real_path")
40
-
41
- case "$shebang" in
42
- "#!/usr/bin/env node"|"#!/data/data/com.termux/files/usr/bin/env node")
43
- sed -i "1s|.*|#!$PREFIX/bin/node|" "$real_path"
44
- log_info "Fixed shebang for $bin_name: $shebang → $PREFIX/bin/node"
45
- ;;
46
- "#!/usr/bin/env bash"|"#!/data/data/com.termux/files/usr/bin/env bash")
47
- sed -i "1s|.*|#!$PREFIX/bin/bash|" "$real_path"
48
- log_info "Fixed shebang for $bin_name: $shebang → $PREFIX/bin/bash"
49
- ;;
50
- esac
51
- }
29
+ import "@/utils/npm-shebang"
52
30
 
53
31
  _batch_npm() {
54
32
  local action="$1"
@@ -2,6 +2,7 @@
2
2
 
3
3
  import "@/utils/log"
4
4
  import "@/utils/version"
5
+ import "@/utils/npm-shebang"
5
6
 
6
7
  LOG_FILE="$KARNEL_CACHE/install_npm.log"
7
8
 
@@ -81,6 +82,7 @@ _update_live_server_npm_impl() {
81
82
  log_error "Failed to update Live Server"
82
83
  return 1
83
84
  fi
85
+ _fix_npm_shebang "live-server"
84
86
  return 0
85
87
  }
86
88
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  import "@/utils/log"
4
4
  import "@/utils/version"
5
+ import "@/utils/npm-shebang"
5
6
 
6
7
  LOG_FILE="$KARNEL_CACHE/install_npm.log"
7
8
 
@@ -42,9 +43,9 @@ _install_localtunnel_npm_impl() {
42
43
  log_error "Failed to install Localtunnel"
43
44
  return 1
44
45
  fi
46
+ _fix_npm_shebang "lt"
45
47
  log_info "Applying localtunnel fix for Android..."
46
48
  _localtunnel_fix_openurl &>>"$LOG_FILE"
47
- _fix_npm_shebang "lt"
48
49
  return 0
49
50
  }
50
51
 
@@ -97,6 +98,7 @@ _update_localtunnel_npm_impl() {
97
98
  log_error "Failed to update Localtunnel"
98
99
  return 1
99
100
  fi
101
+ _fix_npm_shebang "lt"
100
102
  return 0
101
103
  }
102
104
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  import "@/utils/log"
4
4
  import "@/utils/version"
5
+ import "@/utils/npm-shebang"
5
6
 
6
7
  LOG_FILE="$KARNEL_CACHE/install_npm.log"
7
8
 
@@ -80,6 +81,7 @@ _update_markserv_npm_impl() {
80
81
  log_error "Failed to update Markserv"
81
82
  return 1
82
83
  fi
84
+ _fix_npm_shebang "markserv"
83
85
  return 0
84
86
  }
85
87
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  import "@/utils/log"
4
4
  import "@/utils/version"
5
+ import "@/utils/npm-shebang"
5
6
 
6
7
  LOG_FILE="$KARNEL_CACHE/install_npm.log"
7
8
 
@@ -80,6 +81,7 @@ _update_ncu_npm_impl() {
80
81
  log_error "Failed to update NPM Check Updates"
81
82
  return 1
82
83
  fi
84
+ _fix_npm_shebang "ncu"
83
85
  return 0
84
86
  }
85
87
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  import "@/utils/log"
4
4
  import "@/utils/version"
5
+ import "@/utils/npm-shebang"
5
6
 
6
7
  LOG_FILE="$KARNEL_CACHE/install_npm.log"
7
8
 
@@ -80,6 +81,7 @@ _update_nestjs_npm_impl() {
80
81
  log_error "Failed to update NestJS CLI"
81
82
  return 1
82
83
  fi
84
+ _fix_npm_shebang "nest"
83
85
  return 0
84
86
  }
85
87
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  import "@/utils/log"
4
4
  import "@/utils/version"
5
+ import "@/utils/npm-shebang"
5
6
 
6
7
  LOG_FILE="$KARNEL_CACHE/install_npm.log"
7
8
 
@@ -80,6 +81,7 @@ _update_ngrok_npm_impl() {
80
81
  log_error "Failed to update Ngrok"
81
82
  return 1
82
83
  fi
84
+ _fix_npm_shebang "ngrok"
83
85
  return 0
84
86
  }
85
87
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  import "@/utils/log"
4
4
  import "@/utils/version"
5
+ import "@/utils/npm-shebang"
5
6
 
6
7
  LOG_FILE="$KARNEL_CACHE/install_npm.log"
7
8
 
@@ -80,6 +81,7 @@ _update_prettier_npm_impl() {
80
81
  log_error "Failed to update Prettier"
81
82
  return 1
82
83
  fi
84
+ _fix_npm_shebang "prettier"
83
85
  return 0
84
86
  }
85
87
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  import "@/utils/log"
4
4
  import "@/utils/version"
5
+ import "@/utils/npm-shebang"
5
6
 
6
7
  LOG_FILE="$KARNEL_CACHE/install_npm.log"
7
8
 
@@ -80,6 +81,7 @@ _update_psqlformat_npm_impl() {
80
81
  log_error "Failed to update PSQL Format"
81
82
  return 1
82
83
  fi
84
+ _fix_npm_shebang "psqlformat"
83
85
  return 0
84
86
  }
85
87
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  import "@/utils/log"
4
4
  import "@/utils/version"
5
+ import "@/utils/npm-shebang"
5
6
 
6
7
  LOG_FILE="$KARNEL_CACHE/install_npm.log"
7
8
 
@@ -80,6 +81,7 @@ _update_typescript_npm_impl() {
80
81
  log_error "Failed to update TypeScript"
81
82
  return 1
82
83
  fi
84
+ _fix_npm_shebang "tsc"
83
85
  return 0
84
86
  }
85
87
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  import "@/utils/log"
4
4
  import "@/utils/version"
5
+ import "@/utils/npm-shebang"
5
6
 
6
7
  LOG_FILE="$KARNEL_CACHE/install_npm.log"
7
8
 
@@ -80,6 +81,7 @@ _update_vercel_npm_impl() {
80
81
  log_error "Failed to update Vercel CLI"
81
82
  return 1
82
83
  fi
84
+ _fix_npm_shebang "vercel"
83
85
  return 0
84
86
  }
85
87