feat: configurable AI-bridge trigger word for telegram listener
gates / consistency-and-conventions (push) Successful in 1m50s

The listener's "ai " bridge prefix was hard-coded. Messages starting
with <prefix> + space (case-insensitive, literal match) are now
forwarded to Gemini; default stays "ai".

- TELEGRAM_AI_PREFIX in telegram.env (default ai), hot-reloaded per
  message like the command map — no daemon restart needed
- New 'prefix' verb: pos communication telegram listener prefix [word]
  (validated [A-Za-z0-9][A-Za-z0-9_-]*; writes telegram.env chmod 600)
- Field added to the telegram # POS_CONFIG: scope (sender header) so
  'pos config telegram' edits it too
- --status shows the current prefix; usage + POS_SUBCMDS: prefix
  (completions regenerated)
- Matching via scoped nocasematch + quoted-literal =~ prefix;
  ai_bridge_prefix() precedence: env file > env var > default ai

Verified: routing harness (default/custom/case-insensitive/reset/
fallback/unknown-command) green, CLI verb tests, dispatch smoke,
pos config render, gates 0 FAIL 0 WARN.
This commit is contained in:
Your Name
2026-08-27 11:04:37 -04:00
parent 4306a53fef
commit e6fa0a4ee9
7 changed files with 89 additions and 21 deletions
+1
View File
@@ -136,3 +136,4 @@ summary (newest last).
- **2026-08-23** — Menu Phase 2 + firewall style-migration (decision "a" activated: P1 landed, `lib/menu-lib.sh` exists). `pos docker vbox` (157→261): 6-item menu hub over the inline case verbs via a quoted self-invocation `menu_self` (verbs never re-enter the menu → no recursion); `enter` hands over the terminal and returns to the loop; rm/create behind VM-naming y/N. `pos network download` (950→1104): 13-item top-verb map onto existing cmd_* fns — add URL (`menu_ask_value`, optional `--tmux`), gid-pick → info/pause/resume/remove/restart (remove names name+gid before delete), typed-confirm purge, watch handover, daemon start/stop (stop confirmed); non-fatal RPC liveness gate (`-m 3`) keeps queue views alive on a dead daemon; deliberately NOT added to INTERACTIVE_CMDS — menu-lib's tty-guarded reads make membership unnecessary and keep tee-logging for all scripted verbs (survey E-002; Reviewer traced the lint pass as honest through `uses_stdin`). `pos system firewall` (308→325) migrated to repo-standard mechanics ONLY: menu heredoc render → stderr `{ … } >&2` (body byte-preserved), all **38** interactive reads → `/dev/tty` via tool-local `tty_read()` (EOF/no-tty → pointer + rc1, never hangs), `prompt_ipver` de-command-substituted so EOF exits gracefully; root gate / per-cmd confirm / typed RESET / pager / notify / every ufw invocation untouched. Both new tools register `# POS_SUBCMDS:` += `menu`; POS.md rows updated; GEN regen'd. Chain: Builder T4 (`reportAgents/2026-08-23-builder-t4-p2-menus-vbox-download.md`; correctly caught an Orchestrator brief error claiming download was in INTERACTIVE_CMDS) + T5 (`-t5-firewall-menu-migration.md`; pty parity captures vs pre-edit baseline) → Reviewer ACCEPT-WITH-NITS over both (`-reviewer-phase2-menu.md`, transcribed by Orchestrator; recursion/injection analysis, 13/13 mapping proof, four T5 intents verified hunk-by-hunk). Verified: bash -n ×3 + gates green after each pass; final trio re-run by Orchestrator post-T5 — `make check` OK · `make lint` 0 FAIL / 0 WARN (76s under box load ~7; the earlier apparent lint hang was shared-box CPU contention, no code issue). Remaining notes for later sessions: errexit kills whole menu when a backing verb hard-fails (repo-wide pattern, all six menus); `confirm()` EOF hits set-u unbound `yn` (pre-existing common.sh); vbox create EOF at dir prompt degrades to default while name/image prompts abort (cosmetic).
- **2026-08-26** — `pos ai alias` activation rework (Option B) + `pos config` listing readability, per the 2026-08-26 Architect/Designer specs (`AgentsReport/{architect,designer}/2026-08-26-*.md`). **Alias activation:** the stale sourced-snapshot mechanism is gone — every `pos ai alias` invocation runs `_alias_sync()` (two-way reconciliation: render-diff-install of one executable wrapper per ENV record at `~/.local/bin/<name>` chmod 755 via mktemp+mv with a `bash -n` pre-commit guard; marker-guarded deletion of owned wrappers missing from ENV; legacy `ai-aliases.sh` generation stopped and generator-marker-guarded auto-removal with an `unalias <names>` remediation hint; loud PATH guidance when `~/.local/bin` is off PATH). Edits are live on next invocation with no shell reload (kills the reported stale-gemini-alias bug class); create refuses foreign-file and PATH-binary collisions; `show` gains the wrapper path; `pos-system-uninstall` sweeps the wrappers by their line-2 marker in discovery+removal. Dup-table menu bug fixed with a single `_alias_table` renderer (menu option 4 returns to the loop whose pre-render already shows fresh state). **Config readability** (`lib/config-ui.sh`, fully generic): new optional `# POS_CONFIG:` field types — `@Caption` / `@[KEY=v1|v2] Caption` group captions (condition evaluated per render via `cfg_value`; inactive groups dimmed with a textual reason, never hidden → numbering stable; empty-alt segment = unset-as-default) and `*providers=<tag>` adapter filtering (zero match warns once + suppresses its caption); uniform typography tier for ALL scopes (bold title/keys, CYAN rule, dim numbers/placeholders/examples/captions, hanging-indent wrap clamped 60120 cols, whole render block → stderr per menu-lib house pattern, honest prompt `Number to edit [r=refresh, q=quit]:`); masking/edit flow byte-compatible, no per-scope branches. `bin/pos-ai` line-6 header adopted to the caption/tag syntax (single-line change). Verified: stub-PATH harness (`HOME=/tmp/…`, `CONFIG_DIR` seam, argv-capturing `pos` shim) covering %q quoting round-trips (quotes/backticks/`$()`/%/unicode), staleness kill-test, orphan retraction, collision-refusal matrix, legacy migration (marker + foreign), PATH-absent warning, non-tty guard, idempotent double-sync; rendered-output diffs vs Designer mockups for `ai` AND old-format `system`; gates `make gen && make check && make lint` 0 FAIL / 0 WARN.
- **2026-08-27** — Critical fix: paste injection + multiline paste in `pos ai alias`'s Insert Prompt (root cause: `menu_ask_value` → plain line-oriented `read -rp`; a multi-line Ctrl+V paste floods the tty queue, `read` consumes only line one and the rest execute as commands later or get eaten by the next prompt — user-verified `$(whoami)`/`; ls`/`sudo apt update` behavior). New `menu_read_value()` in `lib/menu-lib.sh` (169→362): raw-mode (`stty -icanon -echo -isig min 1 time 0`) bracketed-paste-aware value reader — `\e[?2004h/l` markers, text inside `[200~…[201~` inserted LITERALLY (embedded newlines/CR are data), Enter submits only outside a paste, Backspace/DEL/Left/Right/Home/End/Delete/Ctrl-U edit, Ctrl-D-on-empty + Ctrl-C/Z/\ cancel (terminal restored first); bytes read chunk-wise via `dd bs=4096|od -tx1|tr` — NOT bash's `read` builtin, which self-interrupts on an ETX byte from a tty even with ISIG disabled (SIGINTs the whole script on Ctrl-C); confirmed `read -erp` (readline) atomically consumes a paste but returns only its first line, so a custom reader was required. `bin/pos-ai-alias` (712→760): `_alias_prompt_encode/_decode` (backslash→`\\`, newline→`\n`; literal `[ = ]` comparisons — bash `case` patterns don't match a single backslash), `_alias_prompt_truncate` newline-safe + max-length arg; load/save encode/decode the prompt field; edit wizard shows a truncated display default but Enter restores the FULL original prompt (fixes pre-existing silent truncation of >80-char prompts), empty-original Enter continues. Verified: pty harnesses (`/tmp/pty_{menulib,cancel,e2e_alias}.py`, `/tmp/roundtrip_test.sh`) — bracketed multiline paste captured verbatim incl. `C:\temp\note`/`$(whoami)`/`; ls`/`echo test`/`sudo apt update`, nothing executed, clean exit; single-line paste; Ctrl-D and Ctrl-C both cancel cleanly (CANCELLED→DONE, terminal restored); full create→list→show→edit E2E with decode round-trip and Enter-keeps-full; `bash -n` ×2, `make gen && make check`, `make lint` 0 FAIL / 0 WARN.
- **2026-08-27** — Configurable AI-bridge trigger word for the Telegram listener: the hard-coded `ai ` prefix in `pos-communication-telegram-listener` became `TELEGRAM_AI_PREFIX` (default `ai`) — messages starting with `<prefix> ` (case-insensitive, literal match) are forwarded to Gemini. New `prefix` verb: `pos communication telegram listener prefix` shows the current word, `prefix <word>` sets it (validated `[A-Za-z0-9][A-Za-z0-9_-]*`, writes `TELEGRAM_AI_PREFIX` to `telegram.env` chmod 600); also editable via `pos config telegram` (field added to the sender's `# POS_CONFIG:` telegram scope — registry-driven, no code in config-ui). Matching is per-message hot-reloaded (like the command map — no daemon restart), via scoped `shopt -s nocasematch` + quoted-literal `=~` prefix (bash `case` patterns can't do literal-then-whitespace + case-insensitivity in one test); `ai_bridge_prefix()` precedence: telegram.env > env from load_config > default `ai`. `--status` shows the current prefix; usage + `# POS_SUBCMDS: prefix` added (completions regenerate). Preserved edge: bare `ai` (no trailing space) never matched the old regex, so it still falls through to "Unknown command". Docs: POS.md listener rows/paragraph, howto/ai.md Telegram section + troubleshooting (also corrected a stale claim that AI errors reply with a `pos config ai` hint — code replies `AI error: …` only). Verified: function-level routing harness (`/tmp/ai_prefix_routing_test.sh` — extraction of the real listener functions + PATH stub `pos`): default `ai`/`AI` routes, bare-prefix and unknown-command fallthrough, `ai /reset` and custom-`bot` `/reset` reset the session, custom `bot`/`BOT` routes and old `ai` no longer routes, per-message hot-reload after removing the var; CLI verb tests (show/set/invalid rc 1/leading-digit/`--status`); dispatch smoke `pos communication telegram listener prefix` + flat form; `pos config telegram` render shows the field; `bash -n` ×2, `make gen && make check`, `make lint` 0 FAIL / 0 WARN.
+2 -2
View File
@@ -609,7 +609,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
| `bin/pos-communication-matrix-listener` | 568 | Matrix listener: map /command → bash, run them on room messages |
| `bin/pos-communication-matrix-sender` | 224 | Send messages to a Matrix room via the client-server API (send, test, login) |
| `bin/pos-communication-scrcpy` | 254 | Mirror/control an Android device via scrcpy+adb (mirror, devices, record, tcpip, connect, push, pull, screenshot, info) |
| `bin/pos-communication-telegram-listener` | 566 | Telegram bot listener: map /command → bash, run them on chat messages |
| `bin/pos-communication-telegram-listener` | 623 | Telegram bot listener: map /command → bash, run them on chat messages |
| `bin/pos-communication-telegram-sender` | 221 | Send Telegram messages/files/links/stickers via Bot API (send, test) |
| `bin/pos-docker-compose` | 487 | Docker Compose service manager (ls/up/down/restart/logs/update/config) |
| `bin/pos-docker-health` | 107 | One-glance container health dashboard (exits 1 if unhealthy) |
@@ -644,7 +644,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
| `bin/pos-ai` | 692 | AI assistant: ask, chat, sessions, capture, models, providers |
| `bin/pos-config` | 80 | Interactive editor for the tools' runtime config (reads # POS_CONFIG: registry) |
| `bin/pos-tree` | 118 | Show the pos CLI command tree: categories, commands, and subcommands |
| `completions/pos.bash` | 307 | Dynamic bash completion |
| `completions/pos.bash` | 308 | Dynamic bash completion |
<!-- GEN:END filetable -->
| `apps/install.sh` | 171 | App install/uninstall picker/orchestrator |
+3 -1
View File
@@ -339,8 +339,10 @@ The bot token is a secret — it is stored only in `~/.config/linux_post_install
| `pos communication telegram listener --disable` | Stops, disables, and removes the service |
| `pos communication telegram listener --sync-commands` | Push the mapped `/commands` to the bot's `/` menu (`setMyCommands`) — also run automatically after every map edit, on `--enable`, and at daemon start |
| `pos communication telegram listener --run` | Run the polling loop in the foreground (what the service executes) |
| `pos communication telegram listener prefix` | Show the AI-bridge trigger word (default `ai`) |
| `pos communication telegram listener prefix <word>` | Set the AI-bridge trigger word (one word of letters/digits/`-`/`_`); non-command messages starting with `<word>` + space are answered by Gemini. Also editable via `pos config telegram` (`TELEGRAM_AI_PREFIX`); takes effect immediately, no daemon restart |
The map file is re-read for every message — edits apply without a restart. The listener only reacts to the owner chat (`TELEGRAM_CHAT_ID`); anyone else's message is ignored. `/help` lists mapped commands; an unmapped command replies "Unknown command". Non-command text starting with `ai ` (case-insensitive, e.g. `ai what is Nvidia`) is forwarded to Gemini via `pos ai gemini ask` and the answer is replied verbatim; an AI failure replies the error plus a `pos config ai` hint. Commands run as your user via `timeout 60 bash -c "…"` (stdout + stderr are replied, truncated to ~3800 chars; empty output → `OK`), so `sudo` inside them needs a NOPASSWD rule. A map value prefixed with `@quiet ` runs the command but does NOT reply — for commands that already send their own notification (e.g. `pos system backup` self-notifies, so `/backup=@quiet pos system backup $HOME/Documents` avoids a double message). `--enable` warns if linger is off — the service stops when you log out unless you run `sudo loginctl enable-linger $(whoami)`.
The map file is re-read for every message — edits apply without a restart. The listener only reacts to the owner chat (`TELEGRAM_CHAT_ID`); anyone else's message is ignored. `/help` lists mapped commands; an unmapped command replies "Unknown command". Non-command text starting with `<prefix> ` — default `ai `, configurable via `pos communication telegram listener prefix <word>` or `pos config telegram` — is forwarded to Gemini via `pos ai gemini ask` (case-insensitive, e.g. `ai what is Nvidia` or `BOT what is Nvidia` with prefix `bot`) and the answer is replied verbatim; an AI failure replies the error. Commands run as your user via `timeout 60 bash -c "…"` (stdout + stderr are replied, truncated to ~3800 chars; empty output → `OK`), so `sudo` inside them needs a NOPASSWD rule. A map value prefixed with `@quiet ` runs the command but does NOT reply — for commands that already send their own notification (e.g. `pos system backup` self-notifies, so `/backup=@quiet pos system backup $HOME/Documents` avoids a double message). `--enable` warns if linger is off — the service stops when you log out unless you run `sudo loginctl enable-linger $(whoami)`.
Map entries may carry an optional **description** shown in the bot's `/` menu: `/cmd::short description=bash command` (the description falls back to the bash command, truncated to ~40 chars, when omitted). After every add/edit/remove the command list is pushed to the bot via `setMyCommands`, so the menu stays in sync; an empty map clears the menu. Telegram only registers lowercase `[a-z0-9_]` names (132 chars) — commands like `/Status` or `/my-cmd` are skipped from the menu with a warning but still resolve when typed.
+13 -6
View File
@@ -150,6 +150,11 @@ you: ai what is Nvidia
bot: NVIDIA is a company best known for GPUs...
```
The trigger word is configurable via `pos communication telegram listener
prefix <word>` (or `pos config telegram` → `TELEGRAM_AI_PREFIX`); it takes
effect immediately, so with prefix `bot` you'd message `bot what is Nvidia`.
`pos communication telegram listener prefix` shows the current value.
The bridge lives in the Telegram listener's `handle_message` (it calls
`pos ai ask`); only the owner chat is served, so your key stays private.
Set a different model per message:
@@ -162,13 +167,14 @@ you: ai --model gemini-2.5-flash explain a Raft consensus log
Each chat has its own persistent session (`telegram-<chat id>` — independent
of your terminal's `default` session), so the model
remembers the conversation; `ai /reset` clears it. The listener passes a system
remembers the conversation; `<prefix> /reset` clears it (with the default
prefix that's `ai /reset`). The listener passes a system
prompt telling the model it is answering in a Telegram chat — so it uses emojis
and stays lively — and strips markdown (`**x**`, backticks, `#`, links…) from
the reply before sending it, since messages go out as plain text.
Replying to a message before `ai` makes that message part of the prompt, so
the model can answer about it:
Replying to a message before `<prefix>` makes that message part of the
prompt, so the model can answer about it:
```
you: /status → bot: (system health output…)
@@ -237,9 +243,10 @@ truncated). To disable: `unset __POS_CAPTURE_ACTIVE`.
model's context window; check `pos ai models`.
- `API error 429` → rate limit (free tier); wait and retry, or use a different
model.
- Nothing in Telegram for `ai …` → the listener daemon must be running
(`pos communication telegram listener --status`); the bot token and owner
chat id must match `pos config telegram`.
- Nothing in Telegram for `<prefix> …` (default `ai`) → the listener daemon
must be running (`pos communication telegram listener --status`); the bot
token and owner chat id must match `pos config telegram`. Check the current
trigger word with `pos communication telegram listener prefix`.
---
+68 -11
View File
@@ -2,6 +2,7 @@
set -euo pipefail
# POS: communication telegram-listener — Telegram bot listener: map /command → bash, run them on chat messages
# POS_FLAGS: --enable --disable --status --sync-commands --run
# POS_SUBCMDS: prefix
CONFIG_DIR="${CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/linux_post_install}"
CONFIG_FILE="$CONFIG_DIR/telegram.env"
@@ -10,8 +11,11 @@ API="https://api.telegram.org"
SERVICE="pos-telegram-listener.service"
USER_SYSTEMD_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user"
# System prompt for the "ai " bridge: replies are posted straight into the
# chat, so ask for concise, emoji-friendly Telegram-style answers.
# System prompt for the "<prefix> " AI bridge (default prefix: "ai"): replies
# are posted straight into the chat, so ask for concise, emoji-friendly
# Telegram-style answers. The trigger word is configurable via
# TELEGRAM_AI_PREFIX in telegram.env ('pos communication telegram listener
# prefix <word>' or 'pos config telegram').
AI_SYSTEM="You are a friendly assistant chatting in a Telegram chat. Keep replies concise, use emojis and light formatting to make them lively, and never claim to send messages yourself."
err() { echo "ERROR: $*" >&2; exit 1; }
@@ -32,8 +36,13 @@ Commands:
--sync-commands
Push the mapped /commands to the bot's "/" menu (setMyCommands)
--run Run the polling loop in the foreground (used by the service)
prefix [word]
Show (no argument) or set the AI-bridge trigger word — any
non-command message starting with '<word> ' is answered by
Gemini (default 'ai'). Restore the default with 'prefix ai'.
Config: $CONFIG_FILE (TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID — edit with 'pos config telegram')
Config: $CONFIG_FILE (TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID,
TELEGRAM_AI_PREFIX — edit with 'pos config telegram')
Map: $MAP_FILE — '/cmd=bash command' per line (optional
'/cmd::short description=bash command' shown in the bot menu)
@@ -417,6 +426,8 @@ status() {
fi
echo "config: $CONFIG_FILE"
echo "map file: $MAP_FILE"
load_config
echo "ai prefix: ${TELEGRAM_AI_PREFIX:-ai}"
load_map
echo "commands: $MAP_N mapped"
local i
@@ -425,6 +436,44 @@ status() {
done
}
# ── AI-bridge trigger word (TELEGRAM_AI_PREFIX) ─────────────────
# Show or set the word that starts the AI bridge in handle_message.
# Default 'ai'; a word is [A-Za-z0-9][A-Za-z0-9_-]* (no spaces, no pattern
# metacharacters — the match is a literal, case-insensitive prefix).
prefix_cmd() {
local val="${1:-}"
if [ -z "$val" ]; then
load_config
echo "AI bridge prefix: ${TELEGRAM_AI_PREFIX:-ai}"
echo "Non-command messages starting with '<prefix> ' are answered by Gemini."
echo "Set it with: pos communication telegram listener prefix <word> (default: ai)"
return 0
fi
if ! [[ "$val" =~ ^[A-Za-z0-9][A-Za-z0-9_-]*$ ]]; then
err "invalid prefix '$val' — use one word of letters, digits, '-' or '_' (no spaces)"
fi
mkdir -p "$CONFIG_DIR"
touch "$CONFIG_FILE"
chmod 600 "$CONFIG_FILE"
local tmp
tmp="$(mktemp)"
grep -vE '^TELEGRAM_AI_PREFIX=' "$CONFIG_FILE" > "$tmp" || true
printf 'TELEGRAM_AI_PREFIX=%s\n' "$val" >> "$tmp"
mv "$tmp" "$CONFIG_FILE"
chmod 600 "$CONFIG_FILE"
log "AI bridge prefix set to '$val' — messages starting with '$val ' go to Gemini (takes effect immediately, no restart)"
}
# Current AI-bridge trigger word. Like the command map, re-read per message so
# 'prefix <word>' edits apply without restarting the daemon. Precedence:
# telegram.env > env var from load_config (--run) > default 'ai'.
ai_bridge_prefix() {
local v=""
[ -f "$CONFIG_FILE" ] && v="$(grep -E '^TELEGRAM_AI_PREFIX=' "$CONFIG_FILE" | tail -1 | sed 's/^[^=]*=//; s/^["'\'']//; s/["'\'']$//')" || true
[ -n "$v" ] || v="${TELEGRAM_AI_PREFIX:-ai}"
printf '%s' "$v"
}
# ── polling daemon ──────────────────────────────────────────────
reply() {
local text="$1" msg_id="$2" rc="${3:-}"
@@ -460,14 +509,20 @@ handle_message() {
reply "Mapped commands: $(map_cmds_list)" "$msg_id"
return ;;
esac
# AI bridge: non-command text starting with "ai " (case-insensitive) is
# forwarded to Gemini; the model's answer is replied verbatim. Each chat
# gets its own persistent memory session ("telegram-<chat_id>"); the exact
# prompt "ai /reset" clears it. Future non-command intents (e.g. reminders)
# slot in as more case arms here.
if [[ "$text" != /* && "$text" =~ ^[Aa][Ii][[:space:]](.*)$ ]]; then
# AI bridge: non-command text starting with "<prefix> " (default "ai",
# case-insensitive, configurable via 'pos communication telegram listener
# prefix <word>' / TELEGRAM_AI_PREFIX) is forwarded to Gemini; the model's
# answer is replied verbatim. Each chat gets its own persistent memory
# session ("telegram-<chat_id>"); the exact prompt "<prefix> /reset"
# clears it. Future non-command intents (e.g. reminders) slot in as more
# case arms here.
local prefix
prefix="$(ai_bridge_prefix)"
shopt -s nocasematch
if [[ "$text" != /* && "$text" =~ ^"$prefix"[[:space:]](.*)$ ]]; then
shopt -u nocasematch
local prompt="${BASH_REMATCH[1]}" answer session
[ -n "$prompt" ] || { reply "Usage: ai <prompt> — e.g. 'ai what is Nvidia'" "$msg_id"; return; }
[ -n "$prompt" ] || { reply "Usage: $prefix <prompt> — e.g. '$prefix what is Nvidia'" "$msg_id"; return; }
session="telegram-${TELEGRAM_CHAT_ID}"
if [[ "$prompt" =~ ^/?reset[[:space:]]*$ ]]; then
if pos ai gemini sessions reset "$session" >/dev/null 2>&1; then
@@ -477,7 +532,7 @@ handle_message() {
fi
return
fi
log "ai: $prompt"
log "$prefix: $prompt"
if [ -n "$reply_text" ]; then
prompt="[Reply context — the message you are replying to]\n${reply_text}\n\n${prompt}"
fi
@@ -489,6 +544,7 @@ handle_message() {
fi
return
fi
shopt -u nocasematch
value="$(map_get "$text")"
if [ -z "$value" ]; then
reply "Unknown command: $text (send /help)" "$msg_id"
@@ -561,6 +617,7 @@ case "${1:-}" in
--status) status ;;
--sync-commands) sync_bot_commands ;;
--run) run_daemon ;;
prefix) prefix_cmd "${2:-}" ;;
"") ui ;;
*) err "Unknown option '$1' (see --help)" ;;
esac
+1 -1
View File
@@ -3,7 +3,7 @@ set -euo pipefail
# POS: communication telegram-sender — Send Telegram messages/files/links/stickers via Bot API (send, test)
# POS_FLAGS: --type --caption --parse-mode --no-preview --token --chat-id --markdown
# POS_SUBCMDS: send test
# POS_CONFIG: telegram | telegram.env | TELEGRAM_BOT_TOKEN=secret:Bot token from @BotFather | TELEGRAM_CHAT_ID=digits:Numeric chat id from @userinfobot
# POS_CONFIG: telegram | telegram.env | TELEGRAM_BOT_TOKEN=secret:Bot token from @BotFather | TELEGRAM_CHAT_ID=digits:Numeric chat id from @userinfobot | TELEGRAM_AI_PREFIX=:AI-bridge trigger word in the telegram listener (default ai)::ai
CONFIG_DIR="${CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/linux_post_install}"
CONFIG_FILE="$CONFIG_DIR/telegram.env"
+1
View File
@@ -30,6 +30,7 @@ _pos_subcmds[ai-gemini]="ask chat models sessions capture"
_pos_subcmds[ai-openrouter]="ask chat sessions capture"
_pos_subcmds[communication-matrix-sender]="send test login"
_pos_subcmds[communication-scrcpy]="devices record tcpip connect push pull screenshot info"
_pos_subcmds[communication-telegram-listener]="prefix"
_pos_subcmds[communication-telegram-sender]="send test"
_pos_subcmds[docker-compose]="ls installed up down restart logs update config menu"
_pos_subcmds[docker-vbox]="create enter stop start rm ls menu"