meadows-bot 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. meadows_bot-0.1.0/.env.example +10 -0
  2. meadows_bot-0.1.0/.gitignore +20 -0
  3. meadows_bot-0.1.0/Dockerfile +11 -0
  4. meadows_bot-0.1.0/PKG-INFO +137 -0
  5. meadows_bot-0.1.0/README.md +112 -0
  6. meadows_bot-0.1.0/captain-hooks/backup_files.sh +4 -0
  7. meadows_bot-0.1.0/captain-hooks/restore_files.sh +4 -0
  8. meadows_bot-0.1.0/docker-compose.yml +23 -0
  9. meadows_bot-0.1.0/docs/.gitkeep +0 -0
  10. meadows_bot-0.1.0/pyproject.toml +86 -0
  11. meadows_bot-0.1.0/src/meadows/bot/__about__.py +3 -0
  12. meadows_bot-0.1.0/src/meadows/bot/__init__.py +37 -0
  13. meadows_bot-0.1.0/src/meadows/bot/base.py +972 -0
  14. meadows_bot-0.1.0/src/meadows/bot/chat_bot.py +203 -0
  15. meadows_bot-0.1.0/src/meadows/bot/examples/__init__.py +7 -0
  16. meadows_bot-0.1.0/src/meadows/bot/examples/dependent_bot.py +72 -0
  17. meadows_bot-0.1.0/src/meadows/bot/examples/echo_bot.py +99 -0
  18. meadows_bot-0.1.0/src/meadows/bot/examples/echo_service_bot.py +118 -0
  19. meadows_bot-0.1.0/src/meadows/bot/examples/label_listener_bot.py +137 -0
  20. meadows_bot-0.1.0/src/meadows/bot/examples/math_service_bot.py +149 -0
  21. meadows_bot-0.1.0/src/meadows/bot/examples/rpc_caller_bot.py +162 -0
  22. meadows_bot-0.1.0/src/meadows/bot/examples/sentiment_bot.py +166 -0
  23. meadows_bot-0.1.0/src/meadows/bot/examples/todo_bot.py +331 -0
  24. meadows_bot-0.1.0/src/meadows/bot/export_bot.py +139 -0
  25. meadows_bot-0.1.0/src/meadows/bot/fetch_bot.py +288 -0
  26. meadows_bot-0.1.0/src/meadows/bot/help_bot.py +101 -0
  27. meadows_bot-0.1.0/src/meadows/bot/llm.py +127 -0
  28. meadows_bot-0.1.0/src/meadows/bot/rag_bot.py +196 -0
  29. meadows_bot-0.1.0/src/meadows/bot/slo_bot.py +209 -0
  30. meadows_bot-0.1.0/src/meadows/bot/stats_bot.py +290 -0
  31. meadows_bot-0.1.0/start.sh +2 -0
  32. meadows_bot-0.1.0/tasks.py +66 -0
  33. meadows_bot-0.1.0/tests/conftest.py +186 -0
  34. meadows_bot-0.1.0/tests/test_base.py +662 -0
  35. meadows_bot-0.1.0/tests/test_call_rpc.py +226 -0
  36. meadows_bot-0.1.0/tests/test_chat_bot.py +154 -0
  37. meadows_bot-0.1.0/tests/test_echo.py +153 -0
  38. meadows_bot-0.1.0/tests/test_echo_service_bot.py +110 -0
  39. meadows_bot-0.1.0/tests/test_export_bot.py +133 -0
  40. meadows_bot-0.1.0/tests/test_fetch_bot.py +157 -0
  41. meadows_bot-0.1.0/tests/test_help_bot.py +83 -0
  42. meadows_bot-0.1.0/tests/test_label_listener_bot.py +153 -0
  43. meadows_bot-0.1.0/tests/test_llm.py +111 -0
  44. meadows_bot-0.1.0/tests/test_math_service_bot.py +109 -0
  45. meadows_bot-0.1.0/tests/test_rag_bot.py +148 -0
  46. meadows_bot-0.1.0/tests/test_rpc_caller_bot.py +111 -0
  47. meadows_bot-0.1.0/tests/test_sentiment_bot.py +151 -0
  48. meadows_bot-0.1.0/tests/test_slo_bot.py +157 -0
  49. meadows_bot-0.1.0/tests/test_stats_bot.py +120 -0
  50. meadows_bot-0.1.0/uv.lock +2006 -0
@@ -0,0 +1,10 @@
1
+ # Meadows server URL (the hub this bot connects to)
2
+ MEADOWS_SERVER_URL=http://localhost:8080
3
+
4
+ # Pre-signed JWT token for this bot.
5
+ # Only the server knows the signing key. Generate this token with:
6
+ # cd meadows-server && inv bot-jwt --name=<bot_name> --expiry=1y
7
+ MEADOWS_JWT_TOKEN=
8
+
9
+ # Seconds to wait before disconnecting after an auth error (avoids reconnect loops)
10
+ BOT_AUTH_ERROR_DISCONNECT_DELAY=5
@@ -0,0 +1,20 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .venv/
6
+ venv/
7
+ dist/
8
+ build/
9
+ .pytest_cache/
10
+ .ruff_cache/
11
+
12
+ # edwh / template
13
+ .env
14
+ .toml
15
+
16
+ # OS / editors
17
+ *.swp
18
+ *.bak
19
+ .DS_Store
20
+ *.coverage
@@ -0,0 +1,11 @@
1
+ FROM python:3.13-slim
2
+
3
+ COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
4
+
5
+ WORKDIR /app
6
+ COPY pyproject.toml .
7
+ COPY src/ ./src/
8
+ COPY README.md .
9
+ RUN uv pip install --system --no-cache .
10
+
11
+ CMD ["python", "-c", "import meadows.bot; print('meadows-bot', meadows.bot.__version__)"]
@@ -0,0 +1,137 @@
1
+ Metadata-Version: 2.4
2
+ Name: meadows-bot
3
+ Version: 0.1.0
4
+ Summary: MEADOWS bot SDK: BaseBot, LLMBot. Bot-author-facing package with fast quick-start.
5
+ Author: MEADOWS
6
+ Requires-Python: >=3.12
7
+ Requires-Dist: aiohttp>=3.9.0
8
+ Requires-Dist: meadows-client
9
+ Requires-Dist: meadows-protocol
10
+ Provides-Extra: dependency-heavy
11
+ Requires-Dist: beautifulsoup4>=4.12.0; extra == 'dependency-heavy'
12
+ Requires-Dist: html2text>=2024.2.26; extra == 'dependency-heavy'
13
+ Requires-Dist: httpx>=0.28.0; extra == 'dependency-heavy'
14
+ Requires-Dist: trafilatura>=2.0.0; extra == 'dependency-heavy'
15
+ Provides-Extra: dev
16
+ Requires-Dist: hatch; extra == 'dev'
17
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
18
+ Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
19
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
20
+ Requires-Dist: ruff==0.14.9; extra == 'dev'
21
+ Provides-Extra: examples
22
+ Provides-Extra: llm
23
+ Requires-Dist: httpx>=0.28.0; extra == 'llm'
24
+ Description-Content-Type: text/markdown
25
+
26
+ # meadows-bot
27
+
28
+ > MEADOWS bot SDK: `BaseBot`, `LLMBot`, and ready-to-use bots. Bot-author-facing package with a fast quick-start.
29
+ > Depends on `meadows-client` (transport) and `meadows-protocol` (shapes). Never imports from `meadows-server`.
30
+
31
+ ## What this package contains
32
+
33
+ - `base.py` — `BaseBot`: the SDK core. Auth, reconnect, registration, routing are hidden.
34
+ - `llm.py` — `LLMBot`: minimal abstract LLM bot (no provider specifics in the PoC).
35
+ - `examples/echo_bot.py` — the canonical example bot.
36
+ - Ready-to-use bots (lazy-loaded via `from meadows.bot import HelpBot`, etc.):
37
+ - `help_bot.py` — static help text (`help`, `bots`, `commands`, `groups`, `guide`)
38
+ - `stats_bot.py` — passive monitoring dashboard (`@stats`, `@stats reset`)
39
+ - `chat_bot.py` — LLM conversational assistant via Ollama
40
+ - `fetch_bot.py` — fetches URLs and converts to Markdown
41
+ - `export_bot.py` — exports a thread to a Markdown file
42
+ - `rag_bot.py` — video/audio fragment search via RAG API
43
+ - `slo_bot.py` — Dutch SLO curriculum learning outcome search
44
+
45
+ ## Quick start
46
+
47
+ A working bot is `BOT_NAME` + `should_handle` + `handle` + `connect()`. That's the whole contract.
48
+
49
+ Set the `MEADOWS_JWT_TOKEN` env var (generate with `cd meadows-server && inv bot-jwt --name=mybot --expiry=1y`), then:
50
+
51
+ ```python
52
+ from meadows.bot import BaseBot
53
+
54
+
55
+ class MyBot(BaseBot):
56
+ BOT_NAME = "mybot"
57
+ BOT_DESCRIPTION = "My custom bot"
58
+ BOT_COMMANDS = [{"name": "greet", "description": "Say hello"}]
59
+
60
+ def should_handle(self, command, args):
61
+ return command == "greet"
62
+
63
+ def handle(self, command, args, raw_args, message, thread_context):
64
+ return f"Hello {args[0] if args else 'user'}!"
65
+
66
+
67
+ if __name__ == "__main__":
68
+ MyBot().connect()
69
+ ```
70
+
71
+ ## Install
72
+
73
+ ```bash
74
+ cd meadows-bot
75
+ uv pip install -e .
76
+
77
+ # With extra bots that need HTTP dependencies
78
+ uv pip install -e ".[examples,dependency-heavy,llm]"
79
+ ```
80
+
81
+ ## Test
82
+
83
+ ```bash
84
+ uv run pytest -q
85
+ ```
86
+
87
+ ## Included bots
88
+
89
+ ### Production bots (lazy-loaded via `from meadows.bot import HelpBot`)
90
+
91
+ | Bot | Commands | Deps | Description |
92
+ |-----|----------|------|-------------|
93
+ | `HelpBot` | `help`, `bots`, `commands`, `groups`, `guide` | none | Static help text |
94
+ | `StatsBot` | `@stats`, `@stats reset`, `@stats groups`, `@stats top`, `@stats help` | none | Passive monitoring dashboard; observes all traffic |
95
+ | `ChatBot` | `chat`, `ask`, `vraag`, `praat` | `[llm]` | LLM assistant via Ollama (requires `OLLAMA_URL`) |
96
+ | `FetchBot` | `fetch`, `haal` | `[dependency-heavy]` | Fetches URLs → Markdown |
97
+ | `ExportBot` | `export`, `exporteer` | none | Exports a thread to a Markdown file |
98
+ | `RagBot` | `rag`, `zoek` | none | Video/audio fragment search via RAG API |
99
+ | `SLOBot` | `slo`, `leerdoel` | none | Dutch SLO curriculum learning outcome search |
100
+
101
+ ### Example bots (in `examples/` directory)
102
+
103
+ | Bot | Description |
104
+ |-----|-------------|
105
+ | `EchoBot` | Canonical example bot — echoes messages back |
106
+ | `SentimentBot` | Label producer: sentiment analysis on all messages |
107
+ | `LabelListenerBot` | Label consumer: alerts on angry sentiment |
108
+ | `EchoServiceBot` | Minimal RPC service (echo) |
109
+ | `MathServiceBot` | RPC service (arithmetic) |
110
+ | `RPCCallerBot` | Demonstrates RPC via labels |
111
+ | `TodoBot` | CRUD demo using interactive forms |
112
+
113
+ ## The protocol boundary
114
+
115
+ > The system contracts what it itself must understand. What only bots and humans need to understand stays opaque.
116
+
117
+ This package imports from `meadows.client` (transport) and `meadows.protocol` (shapes), never from `meadows.server`. Server and bot meet only via the protocol declaration. If you find yourself wanting an import from `meadows.server`, something has gone wrong — that belongs in `meadows.protocol` or nowhere.
118
+
119
+ ## Bot-author surface
120
+
121
+ | What | How |
122
+ |---|---|
123
+ | Identity | `BOT_NAME`, `BOT_DESCRIPTION`, `BOT_COMMANDS`, `BOT_CONTEXT_LIMIT` (class attrs) |
124
+ | Decide | `should_handle(command, args) -> bool` (abstract) |
125
+ | Respond | `handle(command, args, raw_args, message, thread_context) -> str \| None` (abstract) |
126
+ | Start | `connect()` — waits 3s for the server, then connects and blocks |
127
+ | Helpers | `log()`, `get_sender_info()`, `format_help_response()`, `extract_quoted_string()` |
128
+ | Patterns | `register_pattern()`, `unregister_pattern()`, `on_pattern_matched()` (decorator) |
129
+ | Labels | `register_label_subscription()`, `unregister_label_subscription()`, `on_label_assigned()`, `emit_label()` |
130
+ | Forms | `send_form()` — send interactive HTML forms, receive submissions via label subscriptions |
131
+ | RPC | `call_rpc()`, `emit_rpc_request()`, `emit_rpc_response()`, `on_rpc_response()` |
132
+ | History | `fetch_messages()` |
133
+ | Lifecycle hooks | `on_connect()`, `on_disconnect()` (passthrough to client) |
134
+
135
+ ## Defaults and errors are pedagogy
136
+
137
+ The target user is not a standard Python developer — it's a Dutch teacher (groep 6) working with an AI during a hackathon. Defaults that "just work" and errors in human language matter more than elegance. A bot that fails silently teaches nothing.
@@ -0,0 +1,112 @@
1
+ # meadows-bot
2
+
3
+ > MEADOWS bot SDK: `BaseBot`, `LLMBot`, and ready-to-use bots. Bot-author-facing package with a fast quick-start.
4
+ > Depends on `meadows-client` (transport) and `meadows-protocol` (shapes). Never imports from `meadows-server`.
5
+
6
+ ## What this package contains
7
+
8
+ - `base.py` — `BaseBot`: the SDK core. Auth, reconnect, registration, routing are hidden.
9
+ - `llm.py` — `LLMBot`: minimal abstract LLM bot (no provider specifics in the PoC).
10
+ - `examples/echo_bot.py` — the canonical example bot.
11
+ - Ready-to-use bots (lazy-loaded via `from meadows.bot import HelpBot`, etc.):
12
+ - `help_bot.py` — static help text (`help`, `bots`, `commands`, `groups`, `guide`)
13
+ - `stats_bot.py` — passive monitoring dashboard (`@stats`, `@stats reset`)
14
+ - `chat_bot.py` — LLM conversational assistant via Ollama
15
+ - `fetch_bot.py` — fetches URLs and converts to Markdown
16
+ - `export_bot.py` — exports a thread to a Markdown file
17
+ - `rag_bot.py` — video/audio fragment search via RAG API
18
+ - `slo_bot.py` — Dutch SLO curriculum learning outcome search
19
+
20
+ ## Quick start
21
+
22
+ A working bot is `BOT_NAME` + `should_handle` + `handle` + `connect()`. That's the whole contract.
23
+
24
+ Set the `MEADOWS_JWT_TOKEN` env var (generate with `cd meadows-server && inv bot-jwt --name=mybot --expiry=1y`), then:
25
+
26
+ ```python
27
+ from meadows.bot import BaseBot
28
+
29
+
30
+ class MyBot(BaseBot):
31
+ BOT_NAME = "mybot"
32
+ BOT_DESCRIPTION = "My custom bot"
33
+ BOT_COMMANDS = [{"name": "greet", "description": "Say hello"}]
34
+
35
+ def should_handle(self, command, args):
36
+ return command == "greet"
37
+
38
+ def handle(self, command, args, raw_args, message, thread_context):
39
+ return f"Hello {args[0] if args else 'user'}!"
40
+
41
+
42
+ if __name__ == "__main__":
43
+ MyBot().connect()
44
+ ```
45
+
46
+ ## Install
47
+
48
+ ```bash
49
+ cd meadows-bot
50
+ uv pip install -e .
51
+
52
+ # With extra bots that need HTTP dependencies
53
+ uv pip install -e ".[examples,dependency-heavy,llm]"
54
+ ```
55
+
56
+ ## Test
57
+
58
+ ```bash
59
+ uv run pytest -q
60
+ ```
61
+
62
+ ## Included bots
63
+
64
+ ### Production bots (lazy-loaded via `from meadows.bot import HelpBot`)
65
+
66
+ | Bot | Commands | Deps | Description |
67
+ |-----|----------|------|-------------|
68
+ | `HelpBot` | `help`, `bots`, `commands`, `groups`, `guide` | none | Static help text |
69
+ | `StatsBot` | `@stats`, `@stats reset`, `@stats groups`, `@stats top`, `@stats help` | none | Passive monitoring dashboard; observes all traffic |
70
+ | `ChatBot` | `chat`, `ask`, `vraag`, `praat` | `[llm]` | LLM assistant via Ollama (requires `OLLAMA_URL`) |
71
+ | `FetchBot` | `fetch`, `haal` | `[dependency-heavy]` | Fetches URLs → Markdown |
72
+ | `ExportBot` | `export`, `exporteer` | none | Exports a thread to a Markdown file |
73
+ | `RagBot` | `rag`, `zoek` | none | Video/audio fragment search via RAG API |
74
+ | `SLOBot` | `slo`, `leerdoel` | none | Dutch SLO curriculum learning outcome search |
75
+
76
+ ### Example bots (in `examples/` directory)
77
+
78
+ | Bot | Description |
79
+ |-----|-------------|
80
+ | `EchoBot` | Canonical example bot — echoes messages back |
81
+ | `SentimentBot` | Label producer: sentiment analysis on all messages |
82
+ | `LabelListenerBot` | Label consumer: alerts on angry sentiment |
83
+ | `EchoServiceBot` | Minimal RPC service (echo) |
84
+ | `MathServiceBot` | RPC service (arithmetic) |
85
+ | `RPCCallerBot` | Demonstrates RPC via labels |
86
+ | `TodoBot` | CRUD demo using interactive forms |
87
+
88
+ ## The protocol boundary
89
+
90
+ > The system contracts what it itself must understand. What only bots and humans need to understand stays opaque.
91
+
92
+ This package imports from `meadows.client` (transport) and `meadows.protocol` (shapes), never from `meadows.server`. Server and bot meet only via the protocol declaration. If you find yourself wanting an import from `meadows.server`, something has gone wrong — that belongs in `meadows.protocol` or nowhere.
93
+
94
+ ## Bot-author surface
95
+
96
+ | What | How |
97
+ |---|---|
98
+ | Identity | `BOT_NAME`, `BOT_DESCRIPTION`, `BOT_COMMANDS`, `BOT_CONTEXT_LIMIT` (class attrs) |
99
+ | Decide | `should_handle(command, args) -> bool` (abstract) |
100
+ | Respond | `handle(command, args, raw_args, message, thread_context) -> str \| None` (abstract) |
101
+ | Start | `connect()` — waits 3s for the server, then connects and blocks |
102
+ | Helpers | `log()`, `get_sender_info()`, `format_help_response()`, `extract_quoted_string()` |
103
+ | Patterns | `register_pattern()`, `unregister_pattern()`, `on_pattern_matched()` (decorator) |
104
+ | Labels | `register_label_subscription()`, `unregister_label_subscription()`, `on_label_assigned()`, `emit_label()` |
105
+ | Forms | `send_form()` — send interactive HTML forms, receive submissions via label subscriptions |
106
+ | RPC | `call_rpc()`, `emit_rpc_request()`, `emit_rpc_response()`, `on_rpc_response()` |
107
+ | History | `fetch_messages()` |
108
+ | Lifecycle hooks | `on_connect()`, `on_disconnect()` (passthrough to client) |
109
+
110
+ ## Defaults and errors are pedagogy
111
+
112
+ The target user is not a standard Python developer — it's a Dutch teacher (groep 6) working with an AI during a hackathon. Defaults that "just work" and errors in human language matter more than elegance. A bot that fails silently teaches nothing.
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+ # Restic file backup (template convention).
3
+ # $HOST, $URI, $SNAPSHOT are provided by the edwh restic plugin at runtime.
4
+ restic $HOST -r $URI backup ./backups --tag files 2>/dev/null || true
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+ # Restic file restore (template convention).
3
+ # $HOST, $URI, $SNAPSHOT are provided by the edwh restic plugin at runtime.
4
+ restic $HOST -r $URI restore $SNAPSHOT --target ./ 2>/dev/null || true
@@ -0,0 +1,23 @@
1
+ networks:
2
+ meadows:
3
+ driver: bridge
4
+ broker:
5
+ external: true
6
+ name: broker
7
+
8
+ services:
9
+ meadows-bot:
10
+ build: .
11
+ image: meadows-bot:latest
12
+ restart: unless-stopped
13
+ environment:
14
+ - MEADOWS_SERVER_URL=${MEADOWS_SERVER_URL:-http://localhost:8080}
15
+ - MEADOWS_JWT_TOKEN=${MEADOWS_JWT_TOKEN}
16
+ - BOT_AUTH_ERROR_DISCONNECT_DELAY=${BOT_AUTH_ERROR_DISCONNECT_DELAY:-5}
17
+ networks:
18
+ - meadows
19
+ logging:
20
+ driver: "json-file"
21
+ options:
22
+ max-size: "100m"
23
+ max-file: "5"
File without changes
@@ -0,0 +1,86 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "meadows-bot"
7
+ version = "0.1.0"
8
+ description = "MEADOWS bot SDK: BaseBot, LLMBot. Bot-author-facing package with fast quick-start."
9
+ readme = "README.md"
10
+ requires-python = ">=3.12"
11
+ license-expression = "MIT"
12
+ authors = [{ name = "MEADOWS" }]
13
+ dependencies = [
14
+ "meadows-protocol",
15
+ "meadows-client",
16
+ "aiohttp>=3.9.0",
17
+ ]
18
+
19
+ [project.optional-dependencies]
20
+ examples = []
21
+ dependency-heavy = ["httpx>=0.28.0", "trafilatura>=2.0.0", "beautifulsoup4>=4.12.0", "html2text>=2024.2.26"]
22
+ llm = ["httpx>=0.28.0"]
23
+ dev = ["hatch", "pytest>=8.0.0", "pytest-asyncio>=0.23.0", "pytest-cov>=5.0.0", "ruff==0.14.9"]
24
+
25
+ [tool.hatch.build.targets.wheel]
26
+ packages = ["src/meadows"]
27
+
28
+ [tool.uv.sources]
29
+ meadows-protocol = { path = "../meadows-protocol", editable = true }
30
+ meadows-client = { path = "../meadows-client", editable = true }
31
+
32
+ [tool.ruff]
33
+ target-version = "py312"
34
+ line-length = 120
35
+
36
+ [tool.ruff.lint]
37
+ select = ["F", "E", "W", "Q", "A", "SIM", "ARG", "PTH", "RUF", "C90", "N", "YTT"]
38
+
39
+ [tool.pytest.ini_options]
40
+ testpaths = ["tests"]
41
+ asyncio_mode = "auto"
42
+
43
+ [tool.vommit]
44
+ allow_breaking_bang = true
45
+ allow_breaking_footer = true
46
+ prerelease_token = "rc"
47
+ confirm = true
48
+
49
+ [tool.vommit.git]
50
+ enabled = true
51
+ origin = "origin"
52
+ branch = "main"
53
+ on_wrong_branch = "error"
54
+ tag_format = "v{version}"
55
+ commit_format = "{version}"
56
+
57
+ [tool.vommit.changelog]
58
+ enabled = true
59
+ file = "CHANGELOG.md"
60
+ include_prereleases = false
61
+ placeholder = "<!-- next-version-placeholder -->"
62
+ placeholder_regex = "<auto>"
63
+ entry_title_format = "## v{version} ({date:%Y-%m-%d})"
64
+
65
+ [tool.vommit.changelog.levels]
66
+ break = "Breaking Change{s}"
67
+ feat = "Feature{s}"
68
+ fix = "Fix{es}"
69
+ perf = "Performance"
70
+ docs = "Documentation"
71
+
72
+ [tool.vommit.pypi]
73
+ enabled = true
74
+ use_keyring = true
75
+
76
+ [tool.vommit.commands]
77
+ clean = "rm -rf ./dist"
78
+ build = "uv build"
79
+ publish = "../pypi-publish"
80
+ post_publish = ""
81
+
82
+ [tool.vommit.version_bump_map]
83
+ break = "major"
84
+ feat = "minor"
85
+ fix = "patch"
86
+ perf = "patch"
@@ -0,0 +1,3 @@
1
+ from importlib.metadata import version
2
+
3
+ __version__ = version("meadows-bot")
@@ -0,0 +1,37 @@
1
+ """MEADOWS bot SDK.
2
+
3
+ BUSINESS RULE (MEADOWS §5 line 131): Document for AI use, because an AI
4
+ writes alongside humans. The existing bot-development-guide.md is the
5
+ pattern to continue: example-first, copy-pasteable, dense tables.
6
+ """
7
+
8
+ from meadows.bot.__about__ import __version__
9
+ from meadows.bot.base import BaseBot
10
+ from meadows.bot.llm import LLMBot
11
+
12
+ __all__ = ["BaseBot", "LLMBot", "__version__"]
13
+
14
+
15
+ def __getattr__(name):
16
+ if name == "HelpBot":
17
+ from meadows.bot.help_bot import HelpBot
18
+ return HelpBot
19
+ if name == "StatsBot":
20
+ from meadows.bot.stats_bot import StatsBot
21
+ return StatsBot
22
+ if name == "RagBot":
23
+ from meadows.bot.rag_bot import RagBot
24
+ return RagBot
25
+ if name == "SLOBot":
26
+ from meadows.bot.slo_bot import SLOBot
27
+ return SLOBot
28
+ if name == "FetchBot":
29
+ from meadows.bot.fetch_bot import FetchBot
30
+ return FetchBot
31
+ if name == "ExportBot":
32
+ from meadows.bot.export_bot import ExportBot
33
+ return ExportBot
34
+ if name == "ChatBot":
35
+ from meadows.bot.chat_bot import ChatBot
36
+ return ChatBot
37
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")