karnel-termux 4.17.20 → 4.17.22
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.
- package/README.md +7 -7
- package/docs/CHANGELOG.md +15 -0
- package/docs/cli/index.md +1 -1
- package/docs/troubleshooting/index.md +3 -3
- package/karnel/RELEASE_COMMIT +1 -1
- package/karnel/cli/commands/agent.sh +9 -5
- package/karnel/cli/commands/brain.sh +18 -14
- package/karnel/cli/commands/ia.sh +5 -1
- package/karnel/cli/commands/open.sh +3 -3
- package/karnel/cli/commands/pg.sh +5 -2
- package/karnel/cli/commands/restore.sh +3 -0
- package/karnel/cli/commands/voice.sh +4 -2
- package/karnel/tools/lang/bun/install.sh +2 -2
- package/karnel/utils/agent_actions.sh +8 -0
- package/karnel/utils/agent_llm.sh +7 -7
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
<p align="center">
|
|
10
10
|
<a href="https://github.com/israelmarques1024-dotcom/karnel-termux">
|
|
11
|
-
<img src="https://img.shields.io/badge/version-4.17.
|
|
11
|
+
<img src="https://img.shields.io/badge/version-4.17.22-0078D4?style=for-the-badge" alt="Version">
|
|
12
12
|
</a>
|
|
13
13
|
<a href="https://www.npmjs.com/package/karnel-termux">
|
|
14
14
|
<img src="https://img.shields.io/npm/v/karnel-termux?style=for-the-badge&logo=npm&color=cb3837" alt="npm">
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
<a href="https://termux.dev/">
|
|
23
23
|
<img src="https://img.shields.io/badge/platform-Termux%20%7C%20Android-0078D4?style=for-the-badge" alt="Platform">
|
|
24
24
|
</a>
|
|
25
|
-
<a href="https://
|
|
26
|
-
<img src="https://img.shields.io/badge/Site-
|
|
25
|
+
<a href="https://karneltermux.vercel.app">
|
|
26
|
+
<img src="https://img.shields.io/badge/Site-karneltermux.vercel.app-0078D4?style=for-the-badge" alt="Website">
|
|
27
27
|
</a>
|
|
28
28
|
</p>
|
|
29
29
|
|
|
@@ -78,7 +78,7 @@ Why it's great:
|
|
|
78
78
|
### Via checksummed GitHub release (recommended)
|
|
79
79
|
|
|
80
80
|
```bash
|
|
81
|
-
version=4.17.
|
|
81
|
+
version=4.17.22
|
|
82
82
|
tmpdir=$(mktemp -d) && trap 'rm -rf "$tmpdir"' EXIT
|
|
83
83
|
base="https://github.com/israelmarques1024-dotcom/karnel-termux/releases/download/v$version"
|
|
84
84
|
curl -fsSL "$base/karnel-termux-install.sh" -o "$tmpdir/karnel-termux-install.sh"
|
|
@@ -526,7 +526,7 @@ karnel open ai # Open AI module docs
|
|
|
526
526
|
karnel open db # Open DB module docs
|
|
527
527
|
```
|
|
528
528
|
|
|
529
|
-
Documentation loads from https://
|
|
529
|
+
Documentation loads from https://karneltermux.vercel.app.
|
|
530
530
|
|
|
531
531
|
---
|
|
532
532
|
|
|
@@ -538,7 +538,7 @@ Documentation loads from https://israelmarques1024-dotcom.github.io/karnel-termu
|
|
|
538
538
|
- [Troubleshooting](https://github.com/israelmarques1024-dotcom/karnel-termux/blob/main/docs/troubleshooting/index.md)
|
|
539
539
|
- [Architecture](https://github.com/israelmarques1024-dotcom/karnel-termux/blob/main/docs/ARCHITECTURE/index.md)
|
|
540
540
|
- [Documentation changelog](https://github.com/israelmarques1024-dotcom/karnel-termux/blob/main/docs/CHANGELOG.md)
|
|
541
|
-
- [Official website](https://
|
|
541
|
+
- [Official website](https://karneltermux.vercel.app)
|
|
542
542
|
|
|
543
543
|
---
|
|
544
544
|
|
|
@@ -673,7 +673,7 @@ MIT © Israel Marques
|
|
|
673
673
|
---
|
|
674
674
|
|
|
675
675
|
<p align="center">
|
|
676
|
-
<a href="https://
|
|
676
|
+
<a href="https://karneltermux.vercel.app">
|
|
677
677
|
<img src="https://img.shields.io/badge/Full%20Documentation-0078D4?style=for-the-badge" alt="Documentation">
|
|
678
678
|
</a>
|
|
679
679
|
</p>
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,21 @@ layout: base
|
|
|
6
6
|
|
|
7
7
|
# Documentation Changelog
|
|
8
8
|
|
|
9
|
+
## 4.17.22
|
|
10
|
+
|
|
11
|
+
- **Data safety and correctness (8):** restore rejects ambiguous multiple archives; Brain preserves same-day title collisions, uses file paths for AI context, initializes/pushes `main`, detects missing `origin`, and supports editors with arguments; PostgreSQL backup filenames are path-safe; AI-session persistence escapes JSON correctly.
|
|
12
|
+
- **Agent safety (3):** positional prompts retain all words, zero-valued execution/context limits are rejected, and PLAN mode rejects shell syntax plus destructive `find`/in-place operations that bypassed its read-only contract.
|
|
13
|
+
- **Installer reliability (1):** Bun proot installation/update no longer reject safe archives before extraction.
|
|
14
|
+
- **Regression coverage:** added critical CLI contracts and strengthened Brain reciprocal-relation coverage; the isolated full suite passes.
|
|
15
|
+
- Version references bumped to `4.17.22`.
|
|
16
|
+
|
|
17
|
+
## 4.17.21
|
|
18
|
+
|
|
19
|
+
- **Official-site routing:** `karnel open`, npm package metadata, and the GitHub/npm README now point to the Vercel production site, `https://karneltermux.vercel.app`, rather than the secondary GitHub Pages mirror.
|
|
20
|
+
- **Open targets:** `karnel open supabase` now opens `/karnel/supabase` and `karnel open cleanup` now opens `/karnel/cleanup`; the old destinations were generic deploy documentation and nonexistent `/cli`, respectively.
|
|
21
|
+
- **Docs clarity:** labeled GitHub Pages as a secondary documentation mirror.
|
|
22
|
+
- Version references bumped to `4.17.21`.
|
|
23
|
+
|
|
9
24
|
## 4.17.20
|
|
10
25
|
|
|
11
26
|
- **PostgreSQL and Supabase (3):**
|
package/docs/cli/index.md
CHANGED
|
@@ -198,7 +198,7 @@ karnel open <target>
|
|
|
198
198
|
```
|
|
199
199
|
|
|
200
200
|
Opens the official documentation page for a module using
|
|
201
|
-
`termux-open-url`. Base URL: `https://
|
|
201
|
+
`termux-open-url`. Base URL: `https://karneltermux.vercel.app`
|
|
202
202
|
|
|
203
203
|
| Target | Opens |
|
|
204
204
|
|------------------|-------|
|
|
@@ -51,14 +51,14 @@ npm publish does not block the release. The workflow needs `contents: write`
|
|
|
51
51
|
permission (already declared). If `gh release create` fails, confirm the tag
|
|
52
52
|
exists and the token used by GitHub Actions has write access.
|
|
53
53
|
|
|
54
|
-
## Documentation
|
|
54
|
+
## Documentation mirror (GitHub Pages)
|
|
55
55
|
|
|
56
|
-
The documentation
|
|
56
|
+
The documentation mirror is a Jekyll (cayman theme) site built from the `docs/`
|
|
57
57
|
directory and published to GitHub Pages by the `Publish Docs` workflow
|
|
58
58
|
(`.github/workflows/docs.yml`) on every push to `main` that changes `docs/**`.
|
|
59
59
|
The workflow runs `actions/jekyll-build-pages` (from `docs/`, output to
|
|
60
60
|
`docs/_site`), uploads the result as a Pages artifact, and deploys it to the
|
|
61
|
-
`github-pages` environment. The
|
|
61
|
+
`github-pages` environment. The mirror is
|
|
62
62
|
`https://israelmarques1024-dotcom.github.io/karnel-termux/`.
|
|
63
63
|
|
|
64
64
|
If a build fails, open the Actions run for the failing job and read the Jekyll
|
package/karnel/RELEASE_COMMIT
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
4c9e5da4c38f3c93a5f36809265feb152fd59b27
|
|
@@ -255,10 +255,11 @@ agent_parse_args() {
|
|
|
255
255
|
AGENT_PROMPT=""
|
|
256
256
|
AGENT_SHOW_HELP=0
|
|
257
257
|
AGENT_YES=0
|
|
258
|
-
local prev=""
|
|
258
|
+
local prev="" prompt_set=0
|
|
259
|
+
local -a positional=()
|
|
259
260
|
for arg in "$@"; do
|
|
260
261
|
case "$prev" in
|
|
261
|
-
-p | --prompt) AGENT_PROMPT="$arg"; prev=""; continue ;;
|
|
262
|
+
-p | --prompt) AGENT_PROMPT="$arg"; prompt_set=1; prev=""; continue ;;
|
|
262
263
|
-m | --model) AGENT_MODEL="$arg"; prev=""; continue ;;
|
|
263
264
|
-u | --endpoint) AGENT_ENDPOINT="$arg"; prev=""; continue ;;
|
|
264
265
|
-t | --temperature) AGENT_TEMPERATURE="$arg"; prev=""; continue ;;
|
|
@@ -267,7 +268,7 @@ agent_parse_args() {
|
|
|
267
268
|
--max-tokens) AGENT_MAX_TOKENS="$arg"; prev=""; continue ;;
|
|
268
269
|
esac
|
|
269
270
|
case "$arg" in
|
|
270
|
-
-p=* | --prompt=*) AGENT_PROMPT="${arg#*=}" ;;
|
|
271
|
+
-p=* | --prompt=*) AGENT_PROMPT="${arg#*=}"; prompt_set=1 ;;
|
|
271
272
|
-m=* | --model=*) AGENT_MODEL="${arg#*=}" ;;
|
|
272
273
|
-u=* | --endpoint=*) AGENT_ENDPOINT="${arg#*=}" ;;
|
|
273
274
|
-t=* | --temperature=*) AGENT_TEMPERATURE="${arg#*=}" ;;
|
|
@@ -280,9 +281,12 @@ agent_parse_args() {
|
|
|
280
281
|
-y | --yes) AGENT_YES=1 ;;
|
|
281
282
|
-h | --help) AGENT_SHOW_HELP=1 ;;
|
|
282
283
|
-*) log_warn "Unknown option: $arg" ;;
|
|
283
|
-
*)
|
|
284
|
+
*) positional+=("$arg") ;;
|
|
284
285
|
esac
|
|
285
286
|
done
|
|
287
|
+
if (( ! prompt_set && ${#positional[@]} )); then
|
|
288
|
+
AGENT_PROMPT="${positional[*]}"
|
|
289
|
+
fi
|
|
286
290
|
}
|
|
287
291
|
readonly AGENT_ASK_SYSTEM="You are a concise chat assistant. Reply in the SAME LANGUAGE the user writes in. Be direct and practical; use markdown, and put code in fenced blocks. <attached_file path=\"...\">...</attached_file> blocks hold real file contents (action=\"no-read\" = path only). <compacted_summary>...</compacted_summary> blocks are condensed summaries of earlier turns — treat them as ground truth."
|
|
288
292
|
|
|
@@ -846,4 +850,4 @@ agent_run_loop() {
|
|
|
846
850
|
_ems=$(agent_timer_ms)
|
|
847
851
|
echo
|
|
848
852
|
printf ' %s[context %s]%s\n' "$D_GRAY" "$(agent_context_footer "$AGENT_REPL_HISTORY" "$_ems")" "$NC"
|
|
849
|
-
}
|
|
853
|
+
}
|
|
@@ -349,7 +349,7 @@ brain_init() {
|
|
|
349
349
|
log_info "Creating private repo: ${D_CYAN}$gh_user/$repo_name${D_NC}..."
|
|
350
350
|
if gh repo create "$repo_name" --private &>/dev/null; then
|
|
351
351
|
(
|
|
352
|
-
git -C "$BRAIN_DIR" init &>/dev/null
|
|
352
|
+
git -C "$BRAIN_DIR" init -b main &>/dev/null || exit 1
|
|
353
353
|
echo "# Karnel Brain" >"$BRAIN_DIR/README.md"
|
|
354
354
|
git -C "$BRAIN_DIR" add -A
|
|
355
355
|
git -C "$BRAIN_DIR" commit -m "init brain" &>/dev/null
|
|
@@ -474,6 +474,10 @@ brain_save() {
|
|
|
474
474
|
# ── Write file ──
|
|
475
475
|
mkdir -p "$BRAIN_DIR/$category"
|
|
476
476
|
local filepath="$BRAIN_DIR/$category/${date_prefix}_${slug}.md"
|
|
477
|
+
if [[ -e "$filepath" ]]; then
|
|
478
|
+
log_error "A memory with this title already exists today: ${date_prefix}_${slug}.md"
|
|
479
|
+
return 1
|
|
480
|
+
fi
|
|
477
481
|
|
|
478
482
|
{
|
|
479
483
|
_brain_frontmatter "$title" "$tags_formatted" "$category" "$related_str"
|
|
@@ -576,6 +580,10 @@ brain_add() {
|
|
|
576
580
|
|
|
577
581
|
mkdir -p "$BRAIN_DIR/$category"
|
|
578
582
|
local filepath="$BRAIN_DIR/$category/${date_prefix}_${slug}.md"
|
|
583
|
+
if [[ -e "$filepath" ]]; then
|
|
584
|
+
log_error "A memory with this title already exists today: ${date_prefix}_${slug}.md"
|
|
585
|
+
return 1
|
|
586
|
+
fi
|
|
579
587
|
|
|
580
588
|
{
|
|
581
589
|
_brain_frontmatter "$title" "$tags_formatted" "$category" ""
|
|
@@ -928,7 +936,7 @@ brain_sync() {
|
|
|
928
936
|
local branch
|
|
929
937
|
branch=$(git -C "$BRAIN_DIR" rev-parse --abbrev-ref HEAD 2>/dev/null)
|
|
930
938
|
|
|
931
|
-
if ! git -C "$BRAIN_DIR" remote -
|
|
939
|
+
if ! git -C "$BRAIN_DIR" remote get-url origin &>/dev/null; then
|
|
932
940
|
log_info "No remote configured — local commit only"
|
|
933
941
|
list_item "Set up GitHub sync with: ${D_CYAN}karnel brain init${D_NC}"
|
|
934
942
|
separator
|
|
@@ -1231,22 +1239,18 @@ brain_edit() {
|
|
|
1231
1239
|
return 0
|
|
1232
1240
|
fi
|
|
1233
1241
|
|
|
1234
|
-
local
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
editor_bin="${editor_bin%% *}"
|
|
1238
|
-
if command -v "$editor_bin" &>/dev/null; then
|
|
1239
|
-
editor="${EDITOR:-nano}"
|
|
1240
|
-
elif [[ -z "$editor" ]] || ! command -v "$editor" &>/dev/null; then
|
|
1242
|
+
local -a editor_cmd=()
|
|
1243
|
+
read -r -a editor_cmd <<< "${EDITOR:-nano}"
|
|
1244
|
+
if ! command -v "${editor_cmd[0]}" &>/dev/null; then
|
|
1241
1245
|
for e in vim nano vi; do
|
|
1242
1246
|
if command -v "$e" &>/dev/null; then
|
|
1243
|
-
|
|
1247
|
+
editor_cmd=("$e")
|
|
1244
1248
|
break
|
|
1245
1249
|
fi
|
|
1246
1250
|
done
|
|
1247
1251
|
fi
|
|
1248
1252
|
|
|
1249
|
-
if [[ -
|
|
1253
|
+
if [[ ${#editor_cmd[@]} -eq 0 ]] || ! command -v "${editor_cmd[0]}" &>/dev/null; then
|
|
1250
1254
|
log_error "No editor found"
|
|
1251
1255
|
list_item "Install one: ${D_CYAN}karnel install editor${D_NC}"
|
|
1252
1256
|
return 1
|
|
@@ -1255,7 +1259,7 @@ brain_edit() {
|
|
|
1255
1259
|
echo
|
|
1256
1260
|
log_info "Opening: ${D_CYAN}$(_brain_title "$file")${D_NC}"
|
|
1257
1261
|
|
|
1258
|
-
"$
|
|
1262
|
+
"${editor_cmd[@]}" "$file"
|
|
1259
1263
|
|
|
1260
1264
|
log_success "Memory updated"
|
|
1261
1265
|
echo
|
|
@@ -1543,7 +1547,7 @@ EOF
|
|
|
1543
1547
|
if [[ -n "$f" ]]; then
|
|
1544
1548
|
matching_files+=("$f")
|
|
1545
1549
|
fi
|
|
1546
|
-
done < <(_brain_rg -i "$clean_query" | head -n 5 || true)
|
|
1550
|
+
done < <(_brain_rg -l -i "$clean_query" | head -n 5 || true)
|
|
1547
1551
|
|
|
1548
1552
|
if [[ ${#matching_files[@]} -eq 0 ]]; then
|
|
1549
1553
|
local -a words=($clean_query)
|
|
@@ -1562,7 +1566,7 @@ EOF
|
|
|
1562
1566
|
if [[ -n "$f" ]]; then
|
|
1563
1567
|
matching_files+=("$f")
|
|
1564
1568
|
fi
|
|
1565
|
-
done < <(_brain_rg -i -e "$word_regex" | head -n 5 || true)
|
|
1569
|
+
done < <(_brain_rg -l -i -e "$word_regex" | head -n 5 || true)
|
|
1566
1570
|
fi
|
|
1567
1571
|
fi
|
|
1568
1572
|
|
|
@@ -420,7 +420,11 @@ PY
|
|
|
420
420
|
ts_raw=$(echo "$session" | cut -d'|' -f2)
|
|
421
421
|
name=$(echo "$session" | cut -d'|' -f3-)
|
|
422
422
|
local escaped_name
|
|
423
|
-
escaped_name=$
|
|
423
|
+
escaped_name=${name//\\/\\\\}
|
|
424
|
+
escaped_name=${escaped_name//\"/\\\"}
|
|
425
|
+
escaped_name=${escaped_name//$'\n'/\\n}
|
|
426
|
+
escaped_name=${escaped_name//$'\r'/\\r}
|
|
427
|
+
escaped_name=${escaped_name//$'\t'/\\t}
|
|
424
428
|
if [[ $first -eq 1 ]]; then
|
|
425
429
|
first=0
|
|
426
430
|
else
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import "@/utils/log"
|
|
4
4
|
import "@/utils/colors"
|
|
5
5
|
|
|
6
|
-
OPEN_DOCS="https://
|
|
6
|
+
OPEN_DOCS="https://karneltermux.vercel.app"
|
|
7
7
|
|
|
8
8
|
open_main() {
|
|
9
9
|
if [[ $# -eq 0 ]]; then
|
|
@@ -25,10 +25,10 @@ open_main() {
|
|
|
25
25
|
url="$OPEN_DOCS/karnel/osint"
|
|
26
26
|
;;
|
|
27
27
|
supabase)
|
|
28
|
-
url="$OPEN_DOCS/karnel/
|
|
28
|
+
url="$OPEN_DOCS/karnel/supabase"
|
|
29
29
|
;;
|
|
30
30
|
cleanup)
|
|
31
|
-
url="$OPEN_DOCS/
|
|
31
|
+
url="$OPEN_DOCS/karnel/cleanup"
|
|
32
32
|
;;
|
|
33
33
|
--help | -h)
|
|
34
34
|
open_help
|
|
@@ -514,7 +514,10 @@ pg_backup() {
|
|
|
514
514
|
log_info "Creating compressed backup for '$db_name'..."
|
|
515
515
|
local backup_dir="$KARNEL_DATA/pg_backups"
|
|
516
516
|
mkdir -p "$backup_dir"
|
|
517
|
-
local
|
|
517
|
+
local safe_db_name
|
|
518
|
+
safe_db_name=$(printf '%s' "$db_name" | tr -c '[:alnum:]_.-' '_')
|
|
519
|
+
[[ -n "$safe_db_name" ]] || { log_error "Invalid database name"; return 1; }
|
|
520
|
+
local file_name="${safe_db_name}_$(date +%Y%m%d_%H%M%S).backup.gz"
|
|
518
521
|
local file_path="$backup_dir/$file_name"
|
|
519
522
|
|
|
520
523
|
if loading "Running backup dump" _run_backup_cmd "$db_name" "$file_path"; then
|
|
@@ -522,7 +525,7 @@ pg_backup() {
|
|
|
522
525
|
log_success "Backup created successfully:"
|
|
523
526
|
list_item "$file_path"
|
|
524
527
|
list_item "Checksum generated: $(cat "${file_path}.sha256")"
|
|
525
|
-
_pg_cleanup_old_backups "$
|
|
528
|
+
_pg_cleanup_old_backups "$safe_db_name"
|
|
526
529
|
else
|
|
527
530
|
log_error "Failed to create backup"
|
|
528
531
|
rm -f "$file_path"
|
|
@@ -107,7 +107,9 @@ voice_main() {
|
|
|
107
107
|
fi
|
|
108
108
|
fi
|
|
109
109
|
|
|
110
|
-
|
|
110
|
+
local -a editor_cmd=()
|
|
111
|
+
read -r -a editor_cmd <<< "${EDITOR:-nano}"
|
|
112
|
+
if ! command -v "${editor_cmd[0]}" &>/dev/null && [[ "$skip_edit" == "false" ]]; then
|
|
111
113
|
log_warn "${EDITOR:-nano} not installed — falling back to --raw mode"
|
|
112
114
|
skip_edit=true
|
|
113
115
|
fi
|
|
@@ -154,7 +156,7 @@ voice_main() {
|
|
|
154
156
|
tmpfile="$(mktemp "${TMPDIR:-${KARNEL_CACHE:-$HOME/.cache/karnel}}/karnel-XXXXXX")"
|
|
155
157
|
echo "$raw" >"$tmpfile"
|
|
156
158
|
$is_text || log_info "Review the prompt in ${EDITOR:-nano}, fix mistakes, then save and quit"
|
|
157
|
-
${
|
|
159
|
+
"${editor_cmd[@]}" "$tmpfile" </dev/tty >/dev/tty || true
|
|
158
160
|
prompt="$(< "$tmpfile")"
|
|
159
161
|
rm -f "$tmpfile"
|
|
160
162
|
elif [[ "$skip_edit" == "false" ]] && ! { [[ -t 0 ]] && [[ -t 1 ]]; }; then
|
|
@@ -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 "(\\.\\./|^\\.\\./|^/)"
|
|
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 "(\\.\\./|^\\.\\./|^/)"
|
|
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 &&
|
|
@@ -551,11 +551,19 @@ _agent_cmd_is_readonly() {
|
|
|
551
551
|
# commands. Anything the write-gate flags, or any command not in this
|
|
552
552
|
# allowlist (ruby/php/lua/tclsh/expect/sbcl/...), is blocked — so PLAN
|
|
553
553
|
# mode can never modify the machine or run arbitrary code.
|
|
554
|
+
# Shell syntax makes a string-level allowlist unsafe: quoted command names,
|
|
555
|
+
# separators, substitutions and redirects can hide writes from the first token.
|
|
556
|
+
case "$1" in
|
|
557
|
+
*';'* | *'&'* | *'|'* | *"'"* | *'"'* | *'`'* | *'\'* | *'<'* | *'>'* | *'$'*) return 1 ;;
|
|
558
|
+
esac
|
|
554
559
|
_agent_cmd_is_write "$1" && return 1
|
|
555
560
|
local first
|
|
556
561
|
first=$(printf '%s\n' "$1" | sed 's/^[[:space:]]*//' | cut -d' ' -f1)
|
|
557
562
|
case "$first" in
|
|
558
563
|
ls | cat | head | tail | grep | rg | find | stat | wc | file | diff | sort | uniq | cut | tr | tree | du | df | which | type | echo | printf | jq | readlink | realpath | date | pwd | whoami | uname | sed)
|
|
564
|
+
if [[ " $1 " == *" -delete "* || " $1 " == *" -exec "* || " $1 " == *" -execdir "* || " $1 " == *" -ok "* || " $1 " == *" -okdir "* || " $1 " == *" -fprint "* || " $1 " == *" -fls "* || " $1 " == *" -i "* ]]; then
|
|
565
|
+
return 1
|
|
566
|
+
fi
|
|
559
567
|
return 0
|
|
560
568
|
;;
|
|
561
569
|
git)
|
|
@@ -50,10 +50,10 @@ agent_config_load() {
|
|
|
50
50
|
# Reject tampered config (defense-in-depth): numeric/boolean fields
|
|
51
51
|
# must match the expected shape or they are reset to safe defaults.
|
|
52
52
|
[[ "$AGENT_TEMPERATURE" =~ ^[0-9]+(\.[0-9]+)?$ ]] || AGENT_TEMPERATURE=0.3
|
|
53
|
-
[[ "$AGENT_MAX_TOKENS" =~ ^[0-9]
|
|
54
|
-
[[ "$AGENT_MAX_ITERATIONS" =~ ^[0-9]
|
|
53
|
+
[[ "$AGENT_MAX_TOKENS" =~ ^[1-9][0-9]*$ ]] || AGENT_MAX_TOKENS=2048
|
|
54
|
+
[[ "$AGENT_MAX_ITERATIONS" =~ ^[1-9][0-9]*$ ]] || AGENT_MAX_ITERATIONS=12
|
|
55
55
|
[[ "$AGENT_CONFIRM_COMMANDS" =~ ^[01]$ ]] || AGENT_CONFIRM_COMMANDS=1
|
|
56
|
-
[[ "$AGENT_CONTEXT_WINDOW" =~ ^[0-9]
|
|
56
|
+
[[ "$AGENT_CONTEXT_WINDOW" =~ ^[1-9][0-9]*$ ]] || AGENT_CONTEXT_WINDOW=8192
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
# ------------------------------------------------------------
|
|
@@ -89,16 +89,16 @@ agent_config_set() {
|
|
|
89
89
|
[[ "$value" =~ ^[0-9]+(\.[0-9]+)?$ ]] || { log_error "temperature must be a number (e.g. 0.3)"; return 1; }
|
|
90
90
|
AGENT_TEMPERATURE="$value" ;;
|
|
91
91
|
max_tokens | maxtokens)
|
|
92
|
-
[[ "$value" =~ ^[0-9]
|
|
92
|
+
[[ "$value" =~ ^[1-9][0-9]*$ ]] || { log_error "max_tokens must be a positive integer"; return 1; }
|
|
93
93
|
AGENT_MAX_TOKENS="$value" ;;
|
|
94
94
|
iterations | max_iterations)
|
|
95
|
-
[[ "$value" =~ ^[0-9]
|
|
95
|
+
[[ "$value" =~ ^[1-9][0-9]*$ ]] || { log_error "iterations must be a positive integer"; return 1; }
|
|
96
96
|
AGENT_MAX_ITERATIONS="$value" ;;
|
|
97
97
|
confirm_commands | confirm)
|
|
98
98
|
[[ "$value" =~ ^[01]$ ]] || { log_error "confirm_commands must be 0 or 1"; return 1; }
|
|
99
99
|
AGENT_CONFIRM_COMMANDS="$value" ;;
|
|
100
100
|
context_window | context)
|
|
101
|
-
[[ "$value" =~ ^[0-9]
|
|
101
|
+
[[ "$value" =~ ^[1-9][0-9]*$ ]] || { log_error "context_window must be a positive integer"; return 1; }
|
|
102
102
|
AGENT_CONTEXT_WINDOW="$value" ;;
|
|
103
103
|
server_command | server) AGENT_SERVER_CMD="$value" ;;
|
|
104
104
|
workspace)
|
|
@@ -363,4 +363,4 @@ agent_history_ensure_system() {
|
|
|
363
363
|
agent_history_drop_system() {
|
|
364
364
|
local history="$1"
|
|
365
365
|
echo "$history" | jq -c '[.[] | select(.role != "system")]'
|
|
366
|
-
}
|
|
366
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "karnel-termux",
|
|
3
|
-
"version": "4.17.
|
|
3
|
+
"version": "4.17.22",
|
|
4
4
|
"description": "Modular Dev Environment for Termux — install languages, databases, AI agents, editors, and more with one command",
|
|
5
5
|
"bin": {
|
|
6
6
|
"karnel": "karnel/bin/karnel"
|
|
@@ -46,5 +46,5 @@
|
|
|
46
46
|
"bugs": {
|
|
47
47
|
"url": "https://github.com/israelmarques1024-dotcom/karnel-termux/issues"
|
|
48
48
|
},
|
|
49
|
-
"homepage": "https://
|
|
49
|
+
"homepage": "https://karneltermux.vercel.app"
|
|
50
50
|
}
|