6.4 KiB
6.4 KiB
Builder Report — Configurable AI-Bridge Trigger Word for the Telegram Listener
Date: 2026-08-27
Status: COMPLETE — implemented, verified, committed (e6fa0a4), pushed
TL;DR
- Request: make the Telegram listener's
ai→ Gemini bridge prefix configurable ("like communication telegram-listener prefix"). - Change: new
TELEGRAM_AI_PREFIXconfig (defaultai) + newprefixverb on the listener; live (per-message) reload like the command map; also editable viapos config telegram. - Files:
bin/pos-communication-telegram-listener566→623,bin/pos-communication-telegram-sender(config-scope field),completions/pos.bash(regen),DOC/AGENT_Context_Project.md(regen filetable row),DOC/POS.md,DOC/howto/ai.md,AGENT_TODO.md. - Verification: function-level routing harness (green), CLI verb tests, dispatch smoke via
pos,pos config telegramrender, gates0 FAIL, 0 WARN. - Commit:
e6fa0a4— pushed (4306a53..e6fa0a4).
[DONE]
1. Design
- Config seam:
TELEGRAM_AI_PREFIXintelegram.env(shared by sender + listener). The listener already had a genericload_config; the key needs no code to load. Added to thetelegram# POS_CONFIG:scope (in the sender's header, which owns that scope) sopos config telegramrenders/edits it — registry-driven, no config-ui code. - CLI verb:
pos communication telegram listener prefix→ shows current word;prefix <word>→ validates[A-Za-z0-9][A-Za-z0-9_-]*(one word, no spaces/pattern metachars, no leading-to avoid flag ambiguity), writesTELEGRAM_AI_PREFIX=totelegram.env(chmod 600, mktemp+mv,grep -vEold line). Registered via# POS_SUBCMDS: prefix→ completions regenerate. - Hot reload: like the command map (re-read per message), a new
ai_bridge_prefix()readstelegram.envper message. Precedence: file > env var fromload_config(daemon start) > defaultai. No daemon restart needed afterprefix <word>. - Matching: literal, case-insensitive prefix followed by whitespace.
casepatterns cannot express "literal word + one space + case-insensitive", so the handler uses a scopedshopt -s nocasematch+ quoted-literal=~:^"$prefix"[[:space:]](.*)$(quoted variable = literal; nocasematch coversAI/Ai/customBoT…). Unset immediately to keep the rest of the handler case-sensitive. - Preserved behavior: bare
ai(no trailing space) never matched the original^[Aa][Ii][[:space:]]regex → still falls through to "Unknown command".ai /reset(or<prefix> /reset) clears the session. Usage/Unknown command/log lines now interpolate the actual prefix.
[DONE]
2. Files Changed
| File | Change |
|---|---|
bin/pos-communication-telegram-listener |
prefix_cmd() (show/set/validate/write), ai_bridge_prefix() (hot-reload resolver), handle_message uses $prefix with scoped nocasematch + literal =~, --status shows ai prefix:, usage() documents prefix, # POS_SUBCMDS: prefix, updated header comments |
bin/pos-communication-telegram-sender |
# POS_CONFIG: telegram scope + TELEGRAM_AI_PREFIX=:AI-bridge trigger word in the telegram listener (default ai)::ai |
completions/pos.bash |
regen: _pos_subcmds[communication-telegram-listener]="prefix" |
DOC/AGENT_Context_Project.md |
regen filetable: listener row 566→623 |
DOC/POS.md |
listener table: two prefix rows; paragraph now says <prefix> (default ai ) configurable via verb/config; corrected stale claim that AI errors reply "plus a pos config ai hint" — code replies AI error: … only |
DOC/howto/ai.md |
Telegram section: trigger word configurable, <prefix> /reset, reply-context wording; troubleshooting points at prefix verb |
AGENT_TODO.md |
dated Done entry |
[DONE]
3. Tests Performed
Routing harness — /tmp/ai_prefix_routing_test.sh
Extracts the listener's real functions (handle_message + deps) via sed, routes messages through them with a PATH-stub pos (fixed: timeout pos … runs a child process, so a bash-function stub is invisible) and a stub reply.
| Case | Result |
|---|---|
ai hello → gemini ask (--session telegram-123 --system … hello), answer replied |
✅ |
AI Hello → routed, prompt kept (case-insensitive) |
✅ |
ai (no space) → Unknown command (preserved edge), no ask |
✅ |
ai (trailing space) → Usage reply |
✅ |
ai /reset → pos ai gemini sessions reset telegram-123, "Memory cleared." |
✅ |
hello → Unknown command (not ai-routed) |
✅ |
TELEGRAM_AI_PREFIX=bot: bot hi → routed; BOT Hi → routed; ai hi → Unknown command |
✅ |
bot /reset → sessions reset |
✅ |
var removed → ai back routed again (hot-reload fallback) |
✅ |
CLI verb — real script, temp CONFIG_DIR
| Test | Result |
|---|---|
prefix (no arg) → AI bridge prefix: ai + usage hint |
✅ |
prefix bot → writes TELEGRAM_AI_PREFIX=bot to telegram.env, rc 0 |
✅ |
prefix after set → AI bridge prefix: bot |
✅ |
prefix 'a b' and prefix 'a.b' → rc 1, validation error |
✅ |
prefix 1ok → accepted (leading digit allowed) |
✅ |
--status → ai prefix: <current> |
✅ |
prefix ai → back to default |
✅ |
Dispatch + config UI
pos communication telegram listener prefixand flatpos communication telegram-listener prefixboth show the current prefix (repobin/poson PATH). ✅pos config telegram(temp dir) rendersTELEGRAM_AI_PREFIXwith its description. ✅
Gates
bash -n ×2 · make gen idempotent · make check OK · make lint 0 FAIL / 0 WARN. ✅
[DONE]
4. Notes / Remaining Risks
- Matrix listener untouched — it has its own hard-coded
ai …bridge (sessionmatrix-<room>); the same treatment is a possible follow-up if wanted. - The daemon still loads
TELEGRAM_BOT_TOKEN/TELEGRAM_CHAT_IDonce at start (unchanged); only the prefix hot-reloads. - A prefix change applies to ALL chats the listener serves (there is one owner chat by design).
- Literal prefix matching means a prefix containing regex metacharacters would be matched literally (quoted), but validation restricts to word chars for predictability.
[DONE]
Status: COMPLETE. The ai trigger is now TELEGRAM_AI_PREFIX (default ai), configurable via pos communication telegram listener prefix <word> or pos config telegram, applied live.