feat: pos ai gemini — CLI + Telegram AI chat (ask, chat, models)
- bin/pos-ai-gemini: one-shot ask (stdout-only, pipe-friendly), interactive multi-turn chat REPL (q/Ctrl+C, /reset), models list; --model override, default gemini-2.5-flash; key via x-goog-api-key header, never printed. - Config scope 'ai' (AI_GEMINI_API_KEY secret, AI_GEMINI_MODEL) in ~/.config/linux_post_install/ai.env via 'pos config ai'; config/ai.env template installed no-clobber by postinstall. - Telegram listener: non-command text starting with 'ai ' (case-insensitive) is answered by Gemini via 'pos ai gemini ask'; owner-chat only, errors reply with the pos config ai hint. Future intents slot in as case arms. - ai-gemini added to INTERACTIVE_CMDS (chat reads stdin). - Docs: POS.md ai section + listener bridge, howto/ai.md, HOWTO/README index rows, bin/pos usage example; make gen refreshed context/completions.
This commit is contained in:
@@ -10,19 +10,19 @@
|
||||
|
||||
<!-- GEN:START docmap -->
|
||||
| ## 1. Project Overview | 28–43 |
|
||||
| ## 2. Directory Structure | 44–181 |
|
||||
| ## 3. Installation Flow | 182–234 |
|
||||
| ## 4. The `pos` CLI System | 235–297 |
|
||||
| ## 5. Shared Library — `lib/common.sh` | 298–329 |
|
||||
| ## 6. Docker Compose / ScaleTail | 330–372 |
|
||||
| ## 7. Optional Apps (`apps/`) | 373–402 |
|
||||
| ## 8. Entertainment Module | 403–416 |
|
||||
| ## 9. Systemd Services | 417–429 |
|
||||
| ## 10. Configuration Files | 430–455 |
|
||||
| ## 11. Coding Conventions | 456–488 |
|
||||
| ## 12. Development Workflow | 489–541 |
|
||||
| ## 13. Key File Quick Reference | 542–590 |
|
||||
| ## 14. Common Tasks for Agents | 591–615 |
|
||||
| ## 2. Directory Structure | 44–183 |
|
||||
| ## 3. Installation Flow | 184–236 |
|
||||
| ## 4. The `pos` CLI System | 237–300 |
|
||||
| ## 5. Shared Library — `lib/common.sh` | 301–332 |
|
||||
| ## 6. Docker Compose / ScaleTail | 333–375 |
|
||||
| ## 7. Optional Apps (`apps/`) | 376–405 |
|
||||
| ## 8. Entertainment Module | 406–419 |
|
||||
| ## 9. Systemd Services | 420–432 |
|
||||
| ## 10. Configuration Files | 433–459 |
|
||||
| ## 11. Coding Conventions | 460–492 |
|
||||
| ## 12. Development Workflow | 493–545 |
|
||||
| ## 13. Key File Quick Reference | 546–595 |
|
||||
| ## 14. Common Tasks for Agents | 596–621 |
|
||||
<!-- GEN:END docmap -->
|
||||
|
||||
## 1. Project Overview
|
||||
@@ -58,6 +58,7 @@ Linux_post_install/
|
||||
├── bin/ # CLI tools — installed to /usr/local/bin/
|
||||
│ ├── pos # Main dispatcher — smart arg matching to pos-* scripts
|
||||
<!-- GEN:START tree -->
|
||||
│ ├── pos-ai-gemini # Chat with Google Gemini (ask, chat, models)
|
||||
│ ├── pos-communication-telegram-listener # Telegram bot listener: map /command → bash, run them on chat messages
|
||||
│ ├── pos-communication-telegram-sender # Send Telegram messages/files/links/stickers via Bot API (send, test)
|
||||
│ ├── pos-config # Interactive editor for the tools' runtime config (reads # POS_CONFIG: registry)
|
||||
@@ -143,7 +144,8 @@ Linux_post_install/
|
||||
│
|
||||
├── config/
|
||||
│ ├── authorized_keys # SSH public keys (gitignored)
|
||||
│ └── entertainment.env # Weather location template (auto-installed by postinstall)
|
||||
│ ├── entertainment.env # Weather location template (auto-installed by postinstall)
|
||||
│ └── ai.env # Gemini API key + model template (auto-installed by postinstall)
|
||||
│
|
||||
├── compose/
|
||||
│ └── scale-tail/ # Git submodule → ScaleTail templates (119+ services)
|
||||
@@ -251,6 +253,7 @@ All non-interactive `pos` commands log output to `~/.local/share/linux_post_inst
|
||||
| Category | Command | Script | Description |
|
||||
|----------|---------|--------|-------------|
|
||||
<!-- GEN:START dispatch -->
|
||||
| ai | gemini | `pos-ai-gemini` | Chat with Google Gemini (ask, chat, models) |
|
||||
| communication | telegram-listener | `pos-communication-telegram-listener` | Telegram bot listener: map /command → bash, run them on chat messages |
|
||||
| communication | telegram-sender | `pos-communication-telegram-sender` | Send Telegram messages/files/links/stickers via Bot API (send, test) |
|
||||
| | config | `pos-config` | Interactive editor for the tools' runtime config (reads # POS_CONFIG: registry) |
|
||||
@@ -440,6 +443,7 @@ All `.service` files in `systemd/` are automatically copied to `/etc/systemd/sys
|
||||
- `~/.config/linux_post_install/entertainment.env` — entertainment plugin defaults: weather location + `ENABLED` auto-trigger list (`plugin, interval` pairs scheduled via `pos entertainment enable/disable`, systemd user timers); auto-installed from `config/entertainment.env` by `postinstall.sh` (no clobber, template printed)
|
||||
- `~/.config/linux_post_install/system.env` — shared "system" tool settings (loaded by `pos system health` / `pos system backup` via `load_system_env()` in `lib/common.sh`; env already exported wins over the file); template `config/system.env`
|
||||
- `~/.config/linux_post_install/notify.env` — alerting platform selection (`NOTIFY_PLATFORM=telegram,matrix`, comma-separated = fan out); read by `lib/notify.sh`; template `config/notify.env`
|
||||
- `~/.config/linux_post_install/ai.env` — Google Gemini config (`AI_GEMINI_API_KEY` secret, `AI_GEMINI_MODEL` default `gemini-2.5-flash`); read by `pos ai gemini`; template `config/ai.env`, auto-installed by postinstall, edit with `pos config ai`
|
||||
- `~/.bashrc` — Modified by postinstall (PATH, bash completion)
|
||||
|
||||
### Feature Flags
|
||||
@@ -555,8 +559,9 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
|
||||
| `bin/flag-clear` | 21 | Unset a flag |
|
||||
| `features/autostart.sh` | 14 | Boot-time feature (moved from `bin/`, flag-gated service) |
|
||||
<!-- GEN:START filetable -->
|
||||
| `bin/pos` | 272 | CLI dispatcher with smart arg matching + logging + category help |
|
||||
| `bin/pos-communication-telegram-listener` | 511 | Telegram bot listener: map /command → bash, run them on chat messages |
|
||||
| `bin/pos` | 277 | CLI dispatcher with smart arg matching + logging + category help |
|
||||
| `bin/pos-ai-gemini` | 197 | Chat with Google Gemini (ask, chat, models) |
|
||||
| `bin/pos-communication-telegram-listener` | 526 | Telegram bot listener: map /command → bash, run them on chat messages |
|
||||
| `bin/pos-communication-telegram-sender` | 220 | Send Telegram messages/files/links/stickers via Bot API (send, test) |
|
||||
| `bin/pos-config` | 80 | Interactive editor for the tools' runtime config (reads # POS_CONFIG: registry) |
|
||||
| `bin/pos-docker-compose` | 366 | Docker Compose service manager (ls/up/down/restart/logs/update/config) |
|
||||
@@ -582,7 +587,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
|
||||
| `bin/pos-system-nfs-server` | 134 | Manage the NFS kernel server (status, share/unshare exports, enable/disable) |
|
||||
| `bin/pos-tree` | 110 | Show the pos CLI command tree: categories, commands, and subcommands |
|
||||
| `bin/pos-usb-server` | 218 | USB Redirector server control (--ls, --share; prompts when args omitted) |
|
||||
| `completions/pos.bash` | 280 | Dynamic bash completion |
|
||||
| `completions/pos.bash` | 282 | Dynamic bash completion |
|
||||
<!-- GEN:END filetable -->
|
||||
| `apps/install.sh` | 171 | App install/uninstall picker/orchestrator |
|
||||
|
||||
@@ -608,6 +613,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
|
||||
| Modify Docker health check | Edit `bin/pos-docker-health` |
|
||||
| Modify vbox (Docker VM) logic | Edit `bin/pos-docker-vbox` |
|
||||
| Modify USB forwarding logic | Edit `bin/pos-usb-server` |
|
||||
| Modify AI/Gemini logic | Edit `bin/pos-ai-gemini` (config scope `ai` via `pos config ai`; `AI_GEMINI_API_KEY`/`AI_GEMINI_MODEL` in `~/.config/linux_post_install/ai.env`) |
|
||||
| Modify UFW/firewall logic | Edit `bin/pos-system-firewall` |
|
||||
| Modify pos logging | Edit log setup in `bin/pos` |
|
||||
| Modify install phases/flags | Edit arg parsing in `install.sh` |
|
||||
|
||||
@@ -9,6 +9,7 @@ authoritative one-line reference (every command + flag), see
|
||||
|
||||
| Category | What you can do | Guide |
|
||||
|----------|-----------------|-------|
|
||||
| `pos ai` | Chat with Google Gemini from CLI or Telegram | [ai](howto/ai.md) |
|
||||
| `pos network` | IP info, hotspot, scan, port check | [network](howto/network.md) |
|
||||
| `pos docker` | Compose services, container dashboards, disposable VMs | [docker](howto/docker.md) |
|
||||
| `pos media` | Download audio/video via yt-dlp | [media](howto/media.md) |
|
||||
@@ -38,6 +39,7 @@ templates (without overwriting an existing file):
|
||||
| `system.env` | `pos system health`, `pos system backup` | `BACKUP_SERVICE_ROOTS`, `HEALTH_BACKUP_MAX_AGE_DAYS` |
|
||||
| `compose.env` | `pos docker compose` | `TS_AUTHKEY`, `TZ`, `DNS_SERVER`, `SERVICES_BASE` |
|
||||
| `entertainment.env` | `pos entertainment *` | plugin keys (`WEATHER_LAT`…), `ENABLED` |
|
||||
| `ai.env` | `pos ai gemini` | `AI_GEMINI_API_KEY`, `AI_GEMINI_MODEL` |
|
||||
|
||||
```bash
|
||||
pos config telegram # set TELEGRAM_BOT_TOKEN / TELEGRAM_CHAT_ID
|
||||
|
||||
+27
-1
@@ -5,6 +5,7 @@
|
||||
- [The dispatcher — `bin/pos`](#the-dispatcher--binpos)
|
||||
- [Logging behavior](#logging-behavior)
|
||||
- [Commands](#commands)
|
||||
- [ai](#ai)
|
||||
- [network](#network)
|
||||
- [docker](#docker)
|
||||
- [media](#media)
|
||||
@@ -52,6 +53,31 @@ Every non-interactive `pos` invocation logs to `~/.local/share/linux_post_instal
|
||||
|
||||
Category-less tools (`config`, `tree`) live outside any category and are documented in their own `###` sections below.
|
||||
|
||||
### ai
|
||||
|
||||
**File:** `bin/pos-ai-gemini`
|
||||
**Purpose:** chat with Google Gemini via the REST API (`generativelanguage.googleapis.com`). One tool, three subcommands: `ask` (one-shot, scriptable), `chat` (interactive multi-turn REPL), and `models` (list `generateContent`-capable ids).
|
||||
|
||||
| Command | Behavior |
|
||||
|---------|----------|
|
||||
| `pos ai gemini ask "<prompt>"` | One-shot; POSTs `generateContent` and prints **only** the answer text to stdout (pipe/script/Telegram-friendly). The prompt may also be piped in via stdin when no argument is given |
|
||||
| `pos ai gemini chat` | Interactive REPL with multi-turn history (the `contents[]` array is appended per turn); `q`/`quit`/`exit` or Ctrl+C quit, `/reset` clears the history, empty input re-prompts |
|
||||
| `pos ai gemini models` | Lists models that support `generateContent` and flags the configured default |
|
||||
| `pos ai gemini --model <id> …` | Overrides the model for one invocation |
|
||||
|
||||
`pos ai gemini` with no subcommand prints usage (never blocks on stdin). `ask`/`chat` time out after 60s per request; on a non-2xx response the API's `error.message` is shown and the tool exits non-zero.
|
||||
|
||||
**Configuration** (`~/.config/linux_post_install/ai.env`, edit with `pos config ai`):
|
||||
|
||||
| Key | Required | Default | Purpose |
|
||||
|-----|----------|---------|---------|
|
||||
| `AI_GEMINI_API_KEY` | yes | — | API key from aistudio.google.com (secret — masked in `pos config ai`) |
|
||||
| `AI_GEMINI_MODEL` | no | `gemini-2.5-flash` | Model id used by `ask`/`chat`/`models` |
|
||||
|
||||
Precedence: `--model` flag > `AI_GEMINI_MODEL` env > config file > `gemini-2.5-flash`. `postinstall.sh` copies the repo's `config/ai.env` template to `~/.config/linux_post_install/ai.env` on install (no clobber). Dependencies: `curl` + `jq` (both in `preinstall.sh` PACKAGES).
|
||||
|
||||
**Telegram bridge:** the Telegram listener forwards non-command messages starting with `ai ` (case-insensitive) to `pos ai gemini ask` and replies with the model's answer — see [communication → listener](#communication).
|
||||
|
||||
### network
|
||||
|
||||
| Command | File | Purpose | Configuration |
|
||||
@@ -228,7 +254,7 @@ The bot token is a secret — it is stored only in `~/.config/linux_post_install
|
||||
| `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) |
|
||||
|
||||
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". 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. `/status=@quiet pos system health --send`), avoiding 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 `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. `/status=@quiet pos system health --send`), avoiding 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 (1–32 chars) — commands like `/Status` or `/my-cmd` are skipped from the menu with a warning but still resolve when typed.
|
||||
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ Everything in this folder is reference material for the `Linux_post_install` pro
|
||||
|
||||
| Document | What it covers |
|
||||
|----------|----------------|
|
||||
| [HOWTO.md](HOWTO.md) | Hands-on guides per category (network, docker, media, system, ssh, usb, communication, entertainment): flags, recipes, config, troubleshooting |
|
||||
| [HOWTO.md](HOWTO.md) | Hands-on guides per category (ai, network, docker, media, system, ssh, usb, communication, entertainment): flags, recipes, config, troubleshooting |
|
||||
| [SCRIPTS.md](SCRIPTS.md) | Core installer scripts: `install.sh`, `preinstall.sh`, `postinstall.sh`, `lib/common.sh`, `lib/flags.sh`, `lib/entertainment-lib.sh`, `features/autostart.sh` — purpose, how each works, configuration |
|
||||
| [POS.md](POS.md) | The `pos` CLI: dispatcher, every `pos-*` command, Docker Compose / ScaleTail config, legacy wrappers, flag CLIs |
|
||||
| [APPS.md](APPS.md) | Optional apps: `apps/install.sh` picker, installer conventions, full app catalog |
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
# How-To: `pos ai`
|
||||
|
||||
Chat with Google Gemini — from the terminal and through the Telegram bot.
|
||||
Tools: `gemini` (`ask`, `chat`, `models`).
|
||||
|
||||
| Tool | What it does |
|
||||
|------|--------------|
|
||||
| `pos ai gemini ask "<prompt>"` | One-shot answer to stdout (scriptable) |
|
||||
| `pos ai gemini chat` | Interactive multi-turn conversation |
|
||||
| `pos ai gemini models` | List available model ids |
|
||||
|
||||
---
|
||||
|
||||
## First run — get a key, configure, chat
|
||||
|
||||
1. Get a free API key from https://aistudio.google.com/apikey (requires a Google
|
||||
account).
|
||||
2. Configure it (masked input):
|
||||
|
||||
```bash
|
||||
pos config ai # enter AI_GEMINI_API_KEY
|
||||
```
|
||||
|
||||
3. Test:
|
||||
|
||||
```bash
|
||||
pos ai gemini ask "Explain DNS in one line"
|
||||
pos ai gemini models # verify the default model id is live
|
||||
pos ai gemini chat # multi-turn conversation
|
||||
```
|
||||
|
||||
`ai.env` lives at `~/.config/linux_post_install/ai.env` (chmod 600); `pos config ai`
|
||||
is the only place the key is written. The key is never printed by `pos`.
|
||||
|
||||
## From the Telegram bot
|
||||
|
||||
Once `pos ai gemini ask` works, any non-command message starting with `ai ` is
|
||||
answered by the model — no bot map entry needed:
|
||||
|
||||
```
|
||||
you: ai what is Nvidia
|
||||
bot: NVIDIA is a company best known for GPUs...
|
||||
```
|
||||
|
||||
The bridge lives in the Telegram listener's `handle_message` (it calls
|
||||
`pos ai gemini ask`); only the owner chat is served, so your key stays private.
|
||||
Set a different model per message:
|
||||
|
||||
```
|
||||
you: ai --model gemini-2.5-flash explain a Raft consensus log
|
||||
```
|
||||
|
||||
## Recipes
|
||||
|
||||
- **Answer from a file:** `pos ai gemini ask "$(cat notes.txt)"`
|
||||
- **Pipe into it:** `echo "fix this: $(cat error.log)" | pos ai gemini ask`
|
||||
- **Answer in a cron job:** `pos ai gemini ask "summarize today's git log" > /tmp/ai_digest.txt`
|
||||
- **Change the default model:**
|
||||
```bash
|
||||
pos config ai # set AI_GEMINI_MODEL, or:
|
||||
AI_GEMINI_MODEL=gemini-2.5-flash pos ai gemini ask "hi"
|
||||
```
|
||||
|
||||
## How it works
|
||||
|
||||
- `ask` POSTs `contents:[{role:user, parts:[{text:"…"}]}]` to
|
||||
`https://generativelanguage.googleapis.com/v1beta/models/<model>:generateContent`
|
||||
with the key in the `x-goog-api-key` header, and prints
|
||||
`.candidates[0].content.parts[].text` — nothing else.
|
||||
- `chat` keeps the whole conversation in memory as a growing `contents[]` array,
|
||||
so later turns have earlier context. `/reset` drops it.
|
||||
- On a non-2xx response the API's `error.message` is shown and the exit code is
|
||||
non-zero — so scripts can rely on `ask` failing loudly.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- `ask` errors "No Gemini API key — run 'pos config ai'" → the key isn't set
|
||||
(or `ai.env` isn't readable). Run `pos config ai`.
|
||||
- `API error 400` → the model id is wrong or the prompt is too long for the
|
||||
model's context window; check `pos ai gemini 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`.
|
||||
|
||||
---
|
||||
|
||||
## Related
|
||||
|
||||
- Reference: [DOC/POS.md → ai](../POS.md#ai)
|
||||
- Telegram bridge context: [communication.md](communication.md)
|
||||
Reference in New Issue
Block a user