diff --git a/DOC/AGENT_Context_Project.md b/DOC/AGENT_Context_Project.md index d68b9a1..b0c3248 100644 --- a/DOC/AGENT_Context_Project.md +++ b/DOC/AGENT_Context_Project.md @@ -10,19 +10,19 @@ | ## 1. Project Overview | 28–43 | -| ## 2. Directory Structure | 44–196 | -| ## 3. Installation Flow | 197–250 | -| ## 4. The `pos` CLI System | 251–324 | -| ## 5. Shared Library — `lib/common.sh` | 325–356 | -| ## 6. Docker Compose / ScaleTail | 357–399 | -| ## 7. Optional Apps (`apps/`) | 400–429 | -| ## 8. Entertainment Module | 430–443 | -| ## 9. Systemd Services | 444–455 | -| ## 10. Configuration Files | 456–482 | -| ## 11. Coding Conventions | 483–515 | -| ## 12. Development Workflow | 516–568 | -| ## 13. Key File Quick Reference | 569–635 | -| ## 14. Common Tasks for Agents | 636–669 | +| ## 2. Directory Structure | 44–197 | +| ## 3. Installation Flow | 198–251 | +| ## 4. The `pos` CLI System | 252–326 | +| ## 5. Shared Library — `lib/common.sh` | 327–358 | +| ## 6. Docker Compose / ScaleTail | 359–401 | +| ## 7. Optional Apps (`apps/`) | 402–431 | +| ## 8. Entertainment Module | 432–445 | +| ## 9. Systemd Services | 446–457 | +| ## 10. Configuration Files | 458–484 | +| ## 11. Coding Conventions | 485–517 | +| ## 12. Development Workflow | 518–570 | +| ## 13. Key File Quick Reference | 571–638 | +| ## 14. Common Tasks for Agents | 639–672 | ## 1. Project Overview @@ -61,7 +61,8 @@ Linux_post_install/ ├── bin/ # CLI tools — installed to /usr/local/bin/ │ ├── pos # Main dispatcher — smart arg matching to pos-* scripts -│ ├── pos-ai-gemini # Chat with Google Gemini (ask, chat, models, sessions) +│ ├── pos-ai-gemini # Chat with Google Gemini (ask, capture, chat, models, sessions) +│ ├── pos-ai-openrouter # Chat with OpenRouter models (ask, capture, chat, models, sessions) │ ├── pos-communication-matrix-listener # Matrix listener: map /command → bash, run them on room messages │ ├── pos-communication-matrix-sender # Send messages to a Matrix room via the client-server API (send, test, login) │ ├── pos-communication-scrcpy # Mirror/control an Android device via scrcpy+adb (mirror, devices, record, tcpip, connect, push, pull, screenshot, info) @@ -267,7 +268,8 @@ All non-interactive `pos` commands log output to `~/.local/share/linux_post_inst | Category | Command | Script | Description | |----------|---------|--------|-------------| -| ai | gemini | `pos-ai-gemini` | Chat with Google Gemini (ask, chat, models, sessions) | +| ai | gemini | `pos-ai-gemini` | Chat with Google Gemini (ask, capture, chat, models, sessions) | +| ai | openrouter | `pos-ai-openrouter` | Chat with OpenRouter models (ask, capture, chat, models, sessions) | | communication | matrix-listener | `pos-communication-matrix-listener` | Matrix listener: map /command → bash, run them on room messages | | communication | matrix-sender | `pos-communication-matrix-sender` | Send messages to a Matrix room via the client-server API (send, test, login) | | communication | scrcpy | `pos-communication-scrcpy` | Mirror/control an Android device via scrcpy+adb (mirror, devices, record, tcpip, connect, push, pull, screenshot, info) | @@ -590,7 +592,8 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:` | `features/usb-automount.sh` | 138 | USB automount feature (udev rule + flag-gated service) | | `bin/pos` | 295 | CLI dispatcher with smart arg matching + logging + category help | -| `bin/pos-ai-gemini` | 311 | Chat with Google Gemini (ask, chat, models, sessions) | +| `bin/pos-ai-gemini` | 586 | Chat with Google Gemini (ask, capture, chat, models, sessions) | +| `bin/pos-ai-openrouter` | 587 | Chat with OpenRouter models (ask, capture, chat, models, sessions) | | `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) | @@ -600,7 +603,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:` | `bin/pos-docker-health` | 107 | One-glance container health dashboard (exits 1 if unhealthy) | | `bin/pos-docker-ps` | 125 | Enhanced container overview (health, IPs, ports, uptime) | | `bin/pos-docker-stack` | 101 | Containers grouped by compose stack (project); standalone group; -a/--all includes stopped | -| `bin/pos-docker-vbox` | 261 | Disposable Docker-based VMs (create/enter/start/stop/rm/ls) | +| `bin/pos-docker-vbox` | 1125 | Disposable Docker-based VMs (create/enter/start/stop/rm/ls) | | `bin/pos-entertainment-config` | 143 | Show or edit the entertainment config (ENABLED auto-trigger list, weather location) | | `bin/pos-entertainment-disable` | 32 | Disable a plugin's auto-trigger (remove it from ENABLED) | | `bin/pos-entertainment-enable` | 49 | Enable an auto-trigger for a plugin on a schedule | @@ -615,9 +618,9 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:` | `bin/pos-network-hotspot` | 93 | Wi-Fi hotspot via create_ap + wihotspot-gui | | `bin/pos-network-ip` | 69 | Show interfaces, routes, public IP + location | | `bin/pos-network-scan` | 272 | Parallel ping sweep of CIDR | -| `bin/pos-share-nfs-client` | 343 | Mount NFS shares (ephemeral or persistent systemd mount units) | +| `bin/pos-share-nfs-client` | 504 | Mount NFS shares (ephemeral or persistent systemd mount units) | | `bin/pos-share-nfs-server` | 245 | Manage the NFS kernel server (status, share/unshare exports, enable/disable) | -| `bin/pos-share-smb-client` | 576 | Mount SMB/CIFS shares (ephemeral or persistent systemd mount units) | +| `bin/pos-share-smb-client` | 764 | Mount SMB/CIFS shares (ephemeral or persistent systemd mount units) | | `bin/pos-share-smb-server` | 441 | Manage the Samba server (status, share/unshare exports, users, enable/disable) | | `bin/pos-share-usb-server` | 362 | USB Redirector server control (--ls, --share; prompts when args omitted) | | `bin/pos-ssh-load-keys` | 31 | Load all SSH keys into the agent | @@ -627,7 +630,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:` | `bin/pos-system-schedule` | 151 | Scheduled jobs: run a command on a timer; notify on threshold/change/error/always or silently | | `bin/pos-config` | 80 | Interactive editor for the tools' runtime config (reads # POS_CONFIG: registry) | | `bin/pos-tree` | 112 | Show the pos CLI command tree: categories, commands, and subcommands | -| `completions/pos.bash` | 302 | Dynamic bash completion | +| `completions/pos.bash` | 305 | Dynamic bash completion | | `apps/install.sh` | 171 | App install/uninstall picker/orchestrator | diff --git a/DOC/POS.md b/DOC/POS.md index 78d1344..6692220 100644 --- a/DOC/POS.md +++ b/DOC/POS.md @@ -56,12 +56,14 @@ Category-less tools (`config`, `tree`) live outside any category and are documen ### 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). +**Purpose:** chat with Google Gemini via the REST API (`generativelanguage.googleapis.com`). One tool, four subcommands: `ask` (scriptable, persistent session), `capture` (run a command and save its output for `--last`), `chat` (interactive multi-turn REPL), and `models` (list `generateContent`-capable ids). | Command | Behavior | |---------|----------| -| `pos ai gemini ask ""` | 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 ask ""` | POSTs `generateContent` and prints the answer text to stdout. The prompt may also be piped in via stdin when no argument is given. Runs in the persistent `default` session (`~/.local/share/linux_post_install/ai/default.json`, capped at 40 turns; `--session ` picks another). Terse by default: a built-in system instruction asks for commands-first minimal prose and to diagnose pasted errors/output with the fix first (`--system ""` replaces it wholesale, `--full` skips it). With `--last`, the output of the most recent logged pos command or captured output (tail, max 4096 chars) is appended to the question. On a tty the answer is rendered as markdown (`glow` if installed, else a built-in renderer); non-tty stdout gets the raw markdown bytes unchanged | +| `pos ai gemini capture ` | Run a command, capture its stdout+stderr to screen and to `~/.local/share/linux_post_install/last_cmd_output` for `--last`. Each capture overwrites the previous one. Returns the command's exit code | +| `pos ai gemini chat` | Interactive REPL with multi-turn history (the `contents[]` array is appended per turn and persisted to the session file — `default` unless `--session`); replies are rendered like `ask` on a tty; `q`/`quit`/`exit` or Ctrl+C quit, `/reset` clears the history, empty input re-prompts | +| `pos ai gemini sessions` | Lists session files with turn counts; `sessions reset ` clears one (e.g. `reset default`) | | `pos ai gemini models` | Lists models that support `generateContent` and flags the configured default | | `pos ai gemini --model …` | Overrides the model for one invocation | @@ -78,6 +80,28 @@ Precedence: `--model` flag > `AI_GEMINI_MODEL` env > config file > `gemini-2.5-f **Messaging bridges:** the Telegram and Matrix listeners forward non-command messages starting with `ai ` (case-insensitive) to `pos ai gemini ask` and reply with the model's answer — see [communication → listener](#communication). The Telegram bridge uses one session per chat (`telegram-`), the Matrix bridge one per room (`matrix-`). +**File:** `bin/pos-ai-openrouter` +**Purpose:** chat with OpenRouter models via the REST API (`openrouter.ai`). One tool, four subcommands: `ask` (scriptable, persistent session), `capture` (run a command and save its output for `--last`), `chat` (interactive multi-turn REPL), and `sessions` (list/clear sessions). OpenRouter provides access to hundreds of models from different providers through a single OpenAI-compatible API. + +| Command | Behavior | +|---------|----------| +| `pos ai openrouter ask ""` | POSTs a chat completion and prints the answer text to stdout. The prompt may also be piped in via stdin when no argument is given. Runs in the persistent `default` session (`~/.local/share/linux_post_install/ai-openrouter/default.json`, capped at 40 turns; `--session ` picks another). Terse by default: a built-in system instruction asks for commands-first minimal prose and to diagnose pasted errors/output with the fix first (`--system ""` replaces it wholesale, `--full` skips it). With `--last`, the output of the most recent logged pos command or captured output (tail, max 4096 chars) is appended to the question. On a tty the answer is rendered as markdown (`glow` if installed, else a built-in renderer); non-tty stdout gets the raw markdown bytes unchanged | +| `pos ai openrouter capture ` | Run a command, capture its stdout+stderr to screen and to `~/.local/share/linux_post_install/last_cmd_output` for `--last`. Each capture overwrites the previous one. Returns the command's exit code | +| `pos ai openrouter chat` | Interactive REPL with multi-turn history (the `messages[]` array is appended per turn and persisted to the session file — `default` unless `--session`); replies are rendered like `ask` on a tty; `q`/`quit`/`exit` or Ctrl+C quit, `/reset` clears the history, empty input re-prompts | +| `pos ai openrouter sessions` | Lists session files with turn counts; `sessions reset ` clears one (e.g. `reset default`) | +| `pos ai openrouter --model …` | Overrides the model for one invocation | + +`pos ai openrouter` 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-openrouter.env`, edit with `pos config ai-openrouter`): + +| Key | Required | Default | Purpose | +|-----|----------|---------|---------| +| `OPENROUTER_API_KEY` | yes | — | API key from openrouter.ai (secret — masked in `pos config ai-openrouter`) | +| `OPENROUTER_MODEL` | no | `openrouter/auto` | Model id used by `ask`/`chat`/`models` | + +Precedence: `--model` flag > `OPENROUTER_MODEL` env > config file > `openrouter/auto`. Dependencies: `curl` + `jq` (both in `preinstall.sh` PACKAGES). + ### network | Command | File | Purpose | Configuration | @@ -200,12 +224,12 @@ Global config keys: | Command | Behavior | |---------|----------| -| `pos docker vbox create [image] [--dir ]` | Creates a container from `ubuntu:22.04` (or the given image), bind-mounting `~/` (or `--dir`, or `.` for cwd) as the working directory; prompts to enter immediately | +| `pos docker vbox create [image] [--dir ]… [--device ]… [--gpu] [--port H:C]… [--cpus N] [--memory SIZE] [--network MODE]` | Creates a container from `ubuntu:22.04` (or the given image), bind-mounting `~/` (or the first `--dir`; repeatable for extra same-path mounts) as the working directory; optional flags add GPU (`--gpus all`), device passthrough, port publishes and cpu/memory limits; prompts to enter immediately | | `pos docker vbox enter ` | Shell into the container (auto-starts it if stopped); detects the working dir from the container mounts | | `pos docker vbox start/stop/rm ` | Start, stop, or force-remove the container | | `pos docker vbox ls` | List vbox containers only (label filter) | -**`pos docker vbox menu`** — bare invocation on a terminal (or the explicit `menu` subcommand) opens an interactive hub wrapping these verbs: list, create (asks name/image/host directory, y/N before anything is pulled), enter (hands the terminal to the container shell — `exit` returns to the menu), start/stop (pick a VM), and remove (y/N confirm naming the VM; `rm -f` removes the container, the host folder is kept). Arguments stay scriptable; without a terminal the menu fails closed with a pointer to these subcommands. +**`pos docker vbox menu`** — bare invocation on a terminal (or the explicit `menu` subcommand) opens an interactive hub wrapping these verbs: list, create (categorized flow: name → category hub with live basket counts — image quick-picks, GPU/Nvidia with automatic toolkit/device-node detection, host devices, dir mounts, ports, CPU/RAM → review screen rendering the exact `docker create` plan before anything runs; 'n' returns to the hub with edits preserved), enter (hands the terminal to the container shell — `exit` returns to the menu), start/stop (pick a VM), and remove (y/N confirm naming the VM; `rm -f` removes the container, the host folder is kept). Arguments stay scriptable; without a terminal the menu fails closed with a pointer to these subcommands. The standalone `vbox` command still works and forwards to `pos docker vbox` (see [Legacy wrappers](#legacy-wrappers)). diff --git a/bin/pos b/bin/pos index 61a86e0..78c142f 100755 --- a/bin/pos +++ b/bin/pos @@ -259,7 +259,7 @@ MAIN_LOG="$LOG_DIR/pos.log" log_cmd() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $* → exit $2" >> "$MAIN_LOG"; } # Commands that read from stdin interactively — only log invocation -INTERACTIVE_CMDS="docker-compose docker-vbox network-hotspot system-firewall media-mp4 media-sync system-backup share-usb-server share-smb-server share-smb-client share-nfs-client share-nfs-server communication-telegram-listener communication-matrix-listener ai-gemini system-schedule entertainment-config config" +INTERACTIVE_CMDS="docker-compose docker-vbox network-hotspot system-firewall media-mp4 media-sync system-backup share-usb-server share-smb-server share-smb-client share-nfs-client share-nfs-server communication-telegram-listener communication-matrix-listener ai-gemini ai-openrouter system-schedule entertainment-config config" for ((i=n-1; i>=0; i--)); do cmd="pos" diff --git a/completions/pos.bash b/completions/pos.bash index d5f5eb6..ea7decf 100644 --- a/completions/pos.bash +++ b/completions/pos.bash @@ -3,11 +3,13 @@ # Install: source this file in ~/.bashrc or place in /etc/bash_completion.d/ # GEN:START posflags declare -A _pos_flags -_pos_flags[ai-gemini]="--model --session --system" +_pos_flags[ai-gemini]="--model --session --system --full --last" +_pos_flags[ai-openrouter]="--model --session --system --full --last" _pos_flags[communication-matrix-listener]="--enable --disable --status --run" _pos_flags[communication-telegram-listener]="--enable --disable --status --sync-commands --run" _pos_flags[communication-telegram-sender]="--type --caption --parse-mode --no-preview --token --chat-id --markdown" _pos_flags[docker-stack]="-a --all" +_pos_flags[docker-vbox]="--dir --gpu --device --port --cpus --memory --network" _pos_flags[entertainment-send]="--print --markdown" _pos_flags[media-mp3]="--output --no-playlist --cookies --by-artist --dry-run" _pos_flags[media-mp4]="--format --best --worst --output --no-playlist --cookies --dry-run" @@ -23,7 +25,8 @@ _pos_flags[tree]="--depth" # GEN:END posflags # GEN:START possubcmds declare -A _pos_subcmds -_pos_subcmds[ai-gemini]="ask chat models sessions" +_pos_subcmds[ai-gemini]="ask capture chat models sessions" +_pos_subcmds[ai-openrouter]="ask capture chat models sessions" _pos_subcmds[communication-matrix-sender]="send test login" _pos_subcmds[communication-scrcpy]="devices record tcpip connect push pull screenshot info" _pos_subcmds[communication-telegram-sender]="send test" @@ -40,7 +43,7 @@ _pos_subcmds[system-backup]="menu" _pos_subcmds[system-schedule]="run list config enable disable status migrate menu" # GEN:END possubcmds # GEN:START posconfigscopes -declare -a _pos_config_scopes=(ai compose entertainment matrix notify scrcpy system telegram ytsync) +declare -a _pos_config_scopes=(ai ai-openrouter compose entertainment matrix notify scrcpy system telegram ytsync) # GEN:END posconfigscopes _pos() {