diff --git a/agent/agency-report b/agent/agency-report index 42ecc03..0f348e6 100755 --- a/agent/agency-report +++ b/agent/agency-report @@ -1,107 +1,32 @@ #!/opt/bux/venv/bin/python -"""agency-report โ€” record + post an Agency suggestion to Telegram. - -Always: - 1. records the suggestion in /var/lib/bux/agency.db - 2. posts the body to TG with inline-keyboard buttons (default 3 in a 2+1 grid) - 3. wires the message_id back into the row so a button tap can record - the user's decision against the right suggestion. - -Default buttons: โœ… Yes ยท ๐Ÿ” More ยท โญ Skip -Default layout: row 1 = [Yes][More], row 2 = [Skip]. - -Each default button has a *kind* the bot uses to pick semantics: - โ€ข Yes โ†’ kind=action โ†’ bot dispatches the suggestion's --prompt in this - topic (the goal's permanent lane). No new forum - topic is spawned โ€” one goal, one topic. - โ€ข More โ†’ kind=more โ†’ bot asks the agent to regenerate this card with - a different angle (different draft, different - framing, different next step). The user is - curious but not sold. - โ€ข Skip โ†’ kind=dismiss โ†’ bot records the dismissal, no LLM call. - (Cheap "saw it, move on".) - -Callback data shape: `agcy:::` where kind is one of -{action, more, dismiss, custom}. Custom button sets passed via --button -all get kind=custom (existing dispatch-in-same-topic behavior). - -Custom buttons: pass --button (repeatable). Layout wraps in pairs of two. - -Canonical card layout (HTML parse mode). Order is locked; the *number* -of expandable blocks is variable (0, 1, 2, N โ€” your call): - - [optional image โ€” skip when text alone is clearer] - headline โ† write the specific action here: - "Reply to on Slack: โ€ฆ" or - "Merge PR #347" โ€” *not* "Agency 95" - or a generic source description. - - -
โ€ฆ
โ† zero or more -
โ€ฆ
- โ€ฆ - - source: โ† at the very end, italic, optional. - - [Yes] [More] - [Skip] - -Blocks are specified via --block (repeatable, JSON object). Each --block -becomes one expandable. Pass any number for 0/1/2/N expandables โ€” typical -copilot card is two (option A / option B). If no --block is passed and a ---prompt is set, a single auto-generated draft block is created so the -user can see what'll run on Yes-tap. - -Yes-tap routing โ€” one goal, one topic: - โ€ข Yes/More dispatch in the topic the card lives in. That topic is the - goal's permanent lane. The agent may create sub-topics later only if - the work genuinely needs fan-out (rare). - โ€ข --spawn-topic / --no-spawn-topic flags are kept for back-compat but - default to OFF inside topics, ON outside topics. The default-button - labels are the same in either case (โœ… Yes / ๐Ÿ” More / โญ Skip). - -If --image (URL), --image-file (local path), or --image-text (auto-rendered -placeholder) is given, the image renders above the body. For bodies that -fit Telegram's 1024-char caption budget the card is sent via sendPhoto; -otherwise it falls back to sendMessage with a large link-preview-image -above the text (visually identical, no length cap). - -`--image-file` uploads a local file via multipart so the model never has -to know the bot token or build a public URL. Auto-detects content type -from the file extension (png/jpg/jpeg/gif/webp). - -`--info-only` strips the inline keyboard entirely. Use for FYI cards -(weekly stats, observations) where there's nothing to act on. The row -is still recorded in the DB so dedup works. - -Field mapping: - --emoji prepended to the bold headline - --title the headline (required) - --source-label short clickable label like "GitHub #347" - --source-url URL the source label links to - --subhead optional one-line under the headline - --image direct image URL - --image-file path to a local image file (multipart upload) - --image-text alt: shorthand text โ†’ auto-generated local card image - --block repeatable; each value is a JSON object - {emoji, title, body[, body_html]} โ†’ one expandable. - Two blocks for option A/B is the typical copilot - card; single block for status confirms. - --prompt exact action that runs if user taps Yes; also - auto-generates a draft block when no --block given. - --importance high|med|low (default med) - --source stable slug for dedupe - --skip-if-exists suppress posting if the source slug already has a - non-pending row - --button repeatable; overrides the default 3-button set. - Custom buttons all get kind=custom. - --info-only omit the inline keyboard entirely (FYI cards). - --thread-id forum topic to post into (defaults to $TG_THREAD_ID) - -Inputs are HTML-escaped by default. To embed raw HTML in --block bodies, -pass `"body_html": true` alongside `"body": ""`. The -`--title-html`, `--subhead-html`, `--source-label-html` long forms remain -for raw HTML in headline / subhead / source label. +"""agency-report โ€” record + post one card to Telegram. + +Three things every call: insert a row in `/var/lib/bux/agency.db`, post +the card to TG (image + expandable blocks + inline-keyboard buttons), +and wire the resulting message_id back into the DB row so a button tap +finds the right suggestion. + +Default buttons: โœ… Yes ยท ๐Ÿ” More ยท โญ Skip. All taps dispatch in the +card's own topic (one-goal-one-topic; if the agent needs a fresh lane +for a big new project, it spawns one explicitly with `tg-schedule +"+1 minute" --fresh`). Yes runs --prompt as a new agent turn; More asks +the agent to regenerate with a different angle; Skip records dismissal, +no LLM call. + +Callback data shape: `agcy:::` where kind โˆˆ +{action, more, dismiss, custom}. Custom --button entries get +kind=custom and dispatch a synthesized `[agency-button]