Files
BLIGHT--CUE/README.md
Spencer a2adda20a8 Update README with Docker webhook setup instructions
Documents the host.docker.internal approach for Gitea running in
a Docker container, including docker-compose config and gotchas.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 21:43:43 -05:00

6.2 KiB

BLIGHT: CUE

A module in the BLIGHT ecosystem.

BLIGHT: CUE monitors Gitea repositories containing markdown files. When a push is received, it scans changed files for BLIGHT: trigger lines, sends the surrounding document to an AI model along with the instruction, and writes the result back to the file in-place — fully automated.


How It Works

  1. You write a BLIGHT: trigger anywhere in a markdown file and push it to Gitea.
  2. Gitea sends a webhook POST to this server.
  3. The server fetches the file, finds all BLIGHT: triggers, and processes them one by one.
  4. Each trigger is replaced with the AI's response at the exact position of the trigger line.
  5. The updated file is committed back to the repo automatically.

Trigger Syntax

BLIGHT: <your instruction here>

Examples:

This paragraph discusses は vs が in Japanese grammar.

BLIGHT: Explain the key differences between は and が based on the paragraph above.

## Next Section
BLIGHT: Spell check this entire document and list any errors found.
BLIGHT: Write a conclusion paragraph for this document.

Failure Behavior

If the AI call fails after 3 attempts, the trigger is replaced with:

<!-- BLIGHT_FAILED: your original instruction -->

You can re-trigger processing by editing the file to restore the original BLIGHT: line and pushing again.


Prerequisites

  • Python 3.10+
  • Access to your Gitea instance (via Tailscale or local network)
  • A Google Gemini API key
  • A Gitea personal access token with repository read/write permissions

Installation

# 1. Clone this repo onto the machine that will run the listener
git clone <this-repo-url>
cd BLIGHT--CUE

# 2. Create and activate a virtual environment
python3 -m venv .venv
source .venv/bin/activate

# 3. Install dependencies
pip install -r requirements.txt

# 4. Copy the example env file and fill in your values
cp .env.example .env

Configuration

Edit .env with your values:

Variable Description
GITEA_URL Base URL of your Gitea instance, no trailing slash
GITEA_TOKEN Personal access token from Gitea → Settings → Applications
GEMINI_API_KEY API key from Google AI Studio
WEBHOOK_SECRET A secret string you choose — must match what you set in Gitea
WEBHOOK_PORT Port the listener binds to (default: 5010)

Running

python app.py

The server binds to 0.0.0.0:5010 (or your configured port). Keep it running as a service or in a screen/tmux session.

For production use, consider running it with a process manager:

# With systemd (example unit file)
# /etc/systemd/system/blight-cue.service
[Unit]
Description=BLIGHT: CUE webhook listener
After=network.target

[Service]
WorkingDirectory=/path/to/Blight_Reader
ExecStart=/path/to/Blight_Reader/.venv/bin/python app.py
Restart=always

[Install]
WantedBy=multi-user.target

Replace /path/to/Blight_Reader with the actual path. The venv Python is at .venv/bin/python relative to the project root — create it with python3 -m venv .venv && .venv/bin/pip install -r requirements.txt.


Registering the Webhook in Gitea

If Gitea runs in Docker

Gitea containers cannot reach localhost on the host directly. The recommended approach is to use host.docker.internal, which Docker resolves to the host machine's IP.

1. Add extra_hosts to your Gitea docker-compose.yml:

services:
  gitea:
    image: gitea/gitea:latest
    # ... your existing config ...
    extra_hosts:
      - "host.docker.internal:host-gateway"

2. Restart Gitea:

docker compose down && docker compose up -d

3. Register the webhook using host.docker.internal as the host (see below), with the Target URL set to:

http://host.docker.internal:5010/webhook

Note: If Gitea is not running when CUE fires, or CUE is not running when Gitea sends a webhook, the delivery will fail. You can use the Redeliver button in the webhook's delivery history to retry without needing to push again.


Registering the Webhook

Do this for each repository you want BLIGHT: CUE to watch.

  1. Open the repository in Gitea.
  2. Go to SettingsWebhooksAdd WebhookGitea.
  3. Set the fields:
    • Target URL: http://host.docker.internal:5010/webhook (Docker) or http://<host-ip>:5010/webhook (non-Docker)
    • HTTP Method: POST
    • Content Type: application/json
    • Secret: the same value as WEBHOOK_SECRET in your .env
    • Trigger On: Push events only
  4. Click Add Webhook, then use Test Delivery to verify connectivity.

AI Provider

BLIGHT: CUE currently uses Google Gemini 2.5 Flash-Lite — the most cost-effective stable Gemini model (~$0.10/$0.40 per million tokens input/output).

Adding a New Provider

All AI providers implement the AIProvider abstract base class in ai/base.py:

from abc import ABC, abstractmethod

class AIProvider(ABC):
    def complete(self, document: str, instruction: str) -> str:
        ...

To add a new provider (e.g. OpenRouter):

  1. Create ai/openrouter.py and implement AIProvider.
  2. In processor.py, replace GeminiProvider() with your new class.

Project Structure

Blight_Reader/
├── app.py              # Flask webhook server
├── processor.py        # Trigger scanning and replacement logic
├── gitea_client.py     # Gitea REST API wrapper
├── config.py           # Environment config loader
├── ai/
│   ├── base.py         # AIProvider abstract base class
│   └── gemini.py       # Gemini 2.5 Flash-Lite implementation
├── requirements.txt
├── .env.example
└── README.md

Part of the BLIGHT Ecosystem

BLIGHT: CUE is one module in a larger modular system called BLIGHT. Each module is independently deployable and communicates through Gitea repositories as the shared data layer.