add: worksop entry & end date for events/workshops & summary change
This commit is contained in:
49
AGENTS.md
Normal file
49
AGENTS.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# AGENTS.md
|
||||
|
||||
## Run
|
||||
```
|
||||
python main.py
|
||||
```
|
||||
Uses `runpy` to exec `bot.py`. No tests, no lint, no CI.
|
||||
|
||||
## Architecture
|
||||
- `bot.py` — Telegram bot (python-telegram-bot), single-worker `asyncio.Queue`, all crawl/parse serialized
|
||||
- `agent.py` — pydantic-ai with local Ollama (`granite4.1:8b`), three agents (opportunity/event/workshop), `output_type=str`
|
||||
- `database.py` — PocketBase client, collections `events` / `opportunities` / `workshops`
|
||||
- `scraper.py` — crawl4ai `AsyncWebCrawler` URL → markdown
|
||||
- `prompts.py` — system prompts for both agent types
|
||||
- `schemas.py` — **unused at runtime**, per file comment: "File doesn't do anything, its just an outline"
|
||||
|
||||
## Windows event-loop quirk
|
||||
DO NOT remove the dual-event-loop pattern in `bot.py`:
|
||||
|
||||
1. PTB runs on `WindowsSelectorEventLoopPolicy` (line 357)
|
||||
2. Scraper runs in a **separate thread** with `WindowsProactorEventLoopPolicy` (line 25) — required for Playwright subprocesses on Windows
|
||||
|
||||
The `get_clean_content()` wrapper in `bot.py` runs `_run_scraper_in_thread` via `ThreadPoolExecutor`. Scraper functions must not be called directly.
|
||||
|
||||
## Agent output format
|
||||
Agents use `output_type=str` (not structured output). JSON is parsed manually from `agent.run()` result:
|
||||
- LLM returns JSON wrapped in `````json ... ````` markdown backticks
|
||||
- `agent.py:56` strips the backtick wrappers before `json.loads()`
|
||||
- The markdown wrapper is specified in `prompts.py` — don't change prompt format without updating the strip logic
|
||||
|
||||
## Date formats
|
||||
- Prompts instruct LLM: `DD-MM-YYYY` (or `DD-MM-YYYY (HH:MM)` for events)
|
||||
- PocketBase expects: `YYYY-MM-DD HH:MM:SS`
|
||||
- `database.py` field mapping: event `date_time` → PocketBase `datetime`, `end_date` → `end_datetime`; workshop same; opportunity `deadline` stays `deadline`
|
||||
|
||||
## PocketBase collections
|
||||
- `events` — fields: `title`, `org`, `datetime`, `end_datetime`, `summary`, `location`, `url`
|
||||
- `opportunities` — fields: `title`, `org`, `type`, `deadline`, `summary`, `location`, `url`
|
||||
- `workshops` — fields: `title`, `org`, `datetime`, `end_datetime`, `summary`, `location`, `url`
|
||||
- Auth uses admin credentials from `.env`
|
||||
|
||||
## Env vars
|
||||
`.env` required: `TG_TOKEN`, `OLLAMA_BASE_URL`, `ALLOWED_USERS`, `POCKETBASE_URL`, `POCKETBASE_ADMIN_EMAIL`, `POCKETBASE_ADMIN_PASSWORD`
|
||||
|
||||
## Auth
|
||||
`ALLOWED_USERS` — comma-separated Telegram user IDs (no brackets). Checked on every command/message handler.
|
||||
|
||||
## Save flow
|
||||
When source is pasted text (not URL), the bot asks for a source URL before saving. `context.user_data` keys: `last_extracted`, `last_source_value`, `last_source_kind`, `last_entry_type`, `awaiting_save_url`, `pending_save_url`, `pending_url_to_process`.
|
||||
Reference in New Issue
Block a user