bub 0.3.6__tar.gz → 0.3.7__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.
- {bub-0.3.6 → bub-0.3.7}/.gitignore +1 -0
- bub-0.3.7/PKG-INFO +189 -0
- bub-0.3.7/README.md +153 -0
- {bub-0.3.6 → bub-0.3.7}/pyproject.toml +2 -4
- bub-0.3.7/src/bub/__init__.py +37 -0
- {bub-0.3.6 → bub-0.3.7}/src/bub/_version.py +2 -2
- {bub-0.3.6 → bub-0.3.7}/src/bub/builtin/agent.py +3 -1
- {bub-0.3.6 → bub-0.3.7}/src/bub/builtin/cli.py +33 -3
- {bub-0.3.6 → bub-0.3.7}/src/bub/builtin/hook_impl.py +114 -6
- {bub-0.3.6 → bub-0.3.7}/src/bub/builtin/settings.py +19 -25
- {bub-0.3.6 → bub-0.3.7}/src/bub/channels/cli/__init__.py +15 -4
- {bub-0.3.6 → bub-0.3.7}/src/bub/channels/cli/renderer.py +8 -4
- {bub-0.3.6 → bub-0.3.7}/src/bub/channels/manager.py +6 -3
- {bub-0.3.6 → bub-0.3.7}/src/bub/channels/telegram.py +9 -4
- bub-0.3.7/src/bub/configure.py +117 -0
- {bub-0.3.6 → bub-0.3.7}/src/bub/framework.py +40 -6
- {bub-0.3.6 → bub-0.3.7}/src/bub/hookspecs.py +9 -5
- bub-0.3.7/src/bub/inquirer.py +86 -0
- bub-0.3.7/src/skills/README.md +7 -0
- bub-0.3.7/tests/conftest.py +39 -0
- {bub-0.3.6 → bub-0.3.7}/tests/test_builtin_agent.py +2 -2
- bub-0.3.7/tests/test_builtin_cli.py +430 -0
- {bub-0.3.6 → bub-0.3.7}/tests/test_builtin_hook_impl.py +5 -4
- {bub-0.3.6 → bub-0.3.7}/tests/test_channels.py +74 -20
- bub-0.3.7/tests/test_configure.py +77 -0
- {bub-0.3.6 → bub-0.3.7}/tests/test_framework.py +121 -23
- {bub-0.3.6 → bub-0.3.7}/tests/test_image_message.py +11 -5
- {bub-0.3.6 → bub-0.3.7}/tests/test_settings.py +29 -35
- bub-0.3.6/PKG-INFO +0 -182
- bub-0.3.6/README.md +0 -148
- bub-0.3.6/src/bub/__init__.py +0 -19
- bub-0.3.6/src/skills/README.md +0 -3
- bub-0.3.6/tests/test_builtin_cli.py +0 -150
- {bub-0.3.6 → bub-0.3.7}/LICENSE +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/bub/__main__.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/bub/builtin/__init__.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/bub/builtin/auth.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/bub/builtin/context.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/bub/builtin/shell_manager.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/bub/builtin/store.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/bub/builtin/tape.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/bub/builtin/tools.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/bub/channels/__init__.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/bub/channels/base.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/bub/channels/handler.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/bub/channels/message.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/bub/envelope.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/bub/hook_runtime.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/bub/skills.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/bub/tools.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/bub/types.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/bub/utils.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/skills/gh/SKILL.md +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/skills/skill-creator/SKILL.md +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/skills/skill-creator/license.txt +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/skills/skill-creator/scripts/init_skill.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/skills/skill-creator/scripts/quick_validate.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/skills/telegram/SKILL.md +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/skills/telegram/scripts/telegram_edit.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/src/skills/telegram/scripts/telegram_send.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/tests/test_builtin_tools.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/tests/test_cli_help.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/tests/test_envelope.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/tests/test_file_tape_store_entry_ids.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/tests/test_fork_store_merge_back.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/tests/test_hook_runtime.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/tests/test_skills.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/tests/test_subagent_tool.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/tests/test_tape_search_output.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/tests/test_tools.py +0 -0
- {bub-0.3.6 → bub-0.3.7}/tests/test_utils.py +0 -0
bub-0.3.7/PKG-INFO
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bub
|
|
3
|
+
Version: 0.3.7
|
|
4
|
+
Summary: A common shape for agents that live alongside people.
|
|
5
|
+
Project-URL: Homepage, https://bub.build
|
|
6
|
+
Project-URL: Repository, https://github.com/bubbuild/bub
|
|
7
|
+
Project-URL: Documentation, https://bub.build
|
|
8
|
+
Author-email: Chojan Shang <psiace@apache.org>, Frost Ming <me@frostming.com>, Yihong <zouzou0208@gmail.com>
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Programming Language :: Python
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Requires-Python: <4.0,>=3.12
|
|
18
|
+
Requires-Dist: aiohttp>=3.13.3
|
|
19
|
+
Requires-Dist: any-llm-sdk[anthropic]
|
|
20
|
+
Requires-Dist: httpx[socks]>=0.28.1
|
|
21
|
+
Requires-Dist: inquirer-textual>=0.5.1
|
|
22
|
+
Requires-Dist: loguru>=0.7.2
|
|
23
|
+
Requires-Dist: pluggy>=1.6.0
|
|
24
|
+
Requires-Dist: prompt-toolkit>=3.0.0
|
|
25
|
+
Requires-Dist: pydantic-settings>=2.0.0
|
|
26
|
+
Requires-Dist: pydantic>=2.0.0
|
|
27
|
+
Requires-Dist: python-telegram-bot>=21.0
|
|
28
|
+
Requires-Dist: pyyaml>=6.0.0
|
|
29
|
+
Requires-Dist: rapidfuzz>=3.14.3
|
|
30
|
+
Requires-Dist: republic>=0.5.4
|
|
31
|
+
Requires-Dist: rich>=13.0.0
|
|
32
|
+
Requires-Dist: typer>=0.9.0
|
|
33
|
+
Provides-Extra: logfire
|
|
34
|
+
Requires-Dist: logfire>=4.31.0; extra == 'logfire'
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
# Bub
|
|
38
|
+
|
|
39
|
+
<div align="center">
|
|
40
|
+
|
|
41
|
+
<picture>
|
|
42
|
+
<source srcset="https://raw.githubusercontent.com/bubbuild/bub/refs/heads/main/website/src/assets/bub-logo-dark.png" media="(prefers-color-scheme: dark)">
|
|
43
|
+
<img alt="Bub logo" src="https://raw.githubusercontent.com/bubbuild/bub/refs/heads/main/website/src/assets/bub-logo.png" width="200">
|
|
44
|
+
</picture>
|
|
45
|
+
|
|
46
|
+
<p><strong>A hook-first runtime for agents that live alongside people.</strong></p>
|
|
47
|
+
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
Bub is a small Python runtime for building agents in shared environments. It started in group chats, where multiple humans and agents had to work in the same conversation without hidden state, hand-wavy memory, or framework-specific magic.
|
|
51
|
+
|
|
52
|
+
Built on [agents.md](https://agents.md/) and [Agent Skills](https://agentskills.io/) , Bub stays intentionally small. Every turn stage is a [pluggy](https://pluggy.readthedocs.io/) hook. Builtins are included but replaceable. The same runtime drives CLI, Telegram, and any channel you add.
|
|
53
|
+
|
|
54
|
+
[Website](https://bub.build) · [GitHub](https://github.com/bubbuild/bub)
|
|
55
|
+
|
|
56
|
+
## Quick Start
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install bub
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Or from source:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
git clone https://github.com/bubbuild/bub.git
|
|
66
|
+
cd bub
|
|
67
|
+
uv sync # enough to run Bub from source
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
For local development, use `make install` instead so the website toolchain and `prek` hooks are installed too.
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
uv run bub chat # interactive session
|
|
74
|
+
uv run bub run "summarize this repo" # one-shot task
|
|
75
|
+
uv run bub gateway # channel listener mode
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Why Bub
|
|
79
|
+
|
|
80
|
+
- **Hook-first runtime.** Every turn stage is a hook. Override one stage or replace the whole flow without forking the runtime.
|
|
81
|
+
- **Tape context.** Context is rebuilt from append-only records, not carried around as mutable session state. Easier to inspect, replay, and hand off.
|
|
82
|
+
- **One runtime across surfaces.** The same inbound pipeline runs across CLI, Telegram, and custom channels. Adapters change the surface, not the runtime model.
|
|
83
|
+
- **Batteries included.** CLI, Telegram, tools, skills, and model execution ship with the core runtime. Use the defaults first, replace them later.
|
|
84
|
+
- **Operator equivalence.** Humans and agents work inside the same runtime boundaries, with the same evidence trail and handoff model. No hidden operator class.
|
|
85
|
+
|
|
86
|
+
## How It Works
|
|
87
|
+
|
|
88
|
+
Every inbound message goes through one turn pipeline. Each stage is a hook.
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
resolve_session → load_state → build_prompt → run_model
|
|
92
|
+
↓
|
|
93
|
+
dispatch_outbound ← render_outbound ← save_state
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Builtins are registered first. External plugins load after them. At runtime, later plugins take precedence. There are no framework-only shortcuts.
|
|
97
|
+
|
|
98
|
+
Key source files:
|
|
99
|
+
|
|
100
|
+
- Turn orchestrator: [`src/bub/framework.py`](https://github.com/bubbuild/bub/blob/main/src/bub/framework.py)
|
|
101
|
+
- Hook contract: [`src/bub/hookspecs.py`](https://github.com/bubbuild/bub/blob/main/src/bub/hookspecs.py)
|
|
102
|
+
- Builtin hooks: [`src/bub/builtin/hook_impl.py`](https://github.com/bubbuild/bub/blob/main/src/bub/builtin/hook_impl.py)
|
|
103
|
+
- Skill discovery: [`src/bub/skills.py`](https://github.com/bubbuild/bub/blob/main/src/bub/skills.py)
|
|
104
|
+
|
|
105
|
+
## Extend It
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
from bub import hookimpl
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class EchoPlugin:
|
|
112
|
+
@hookimpl
|
|
113
|
+
def build_prompt(self, message, session_id, state):
|
|
114
|
+
return f"[echo] {message['content']}"
|
|
115
|
+
|
|
116
|
+
@hookimpl
|
|
117
|
+
async def run_model(self, prompt, session_id, state):
|
|
118
|
+
return prompt
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
```toml
|
|
122
|
+
[project.entry-points."bub"]
|
|
123
|
+
echo = "my_package.plugin:EchoPlugin"
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
See the [Extending docs](https://bub.build/docs/extending/) for hook guides, packaging, and plugin structure.
|
|
127
|
+
|
|
128
|
+
## CLI
|
|
129
|
+
|
|
130
|
+
| Command | Description |
|
|
131
|
+
| ------------------ | --------------------------------- |
|
|
132
|
+
| `bub chat` | Interactive REPL |
|
|
133
|
+
| `bub run MESSAGE` | One-shot turn |
|
|
134
|
+
| `bub gateway` | Channel listener (Telegram, etc.) |
|
|
135
|
+
| `bub install` | Install or sync Bub plugin deps |
|
|
136
|
+
| `bub update` | Upgrade Bub plugin deps |
|
|
137
|
+
| `bub login openai` | OpenAI Codex OAuth |
|
|
138
|
+
|
|
139
|
+
Lines starting with `,` enter internal command mode (`,help`, `,skill name=my-skill`, `,fs.read path=README.md`).
|
|
140
|
+
|
|
141
|
+
`bub hooks` still exists for diagnostics, but it is hidden from top-level help. `bub install` and `bub update` manage a separate uv project for Bub plugins, defaulting to `~/.bub/bub-project` or `BUB_PROJECT`.
|
|
142
|
+
|
|
143
|
+
## Configuration
|
|
144
|
+
|
|
145
|
+
| Variable | Default | Description |
|
|
146
|
+
| --------------------------- | ---------------------------- | ---------------------------------------------------- |
|
|
147
|
+
| `BUB_MODEL` | `openrouter:openrouter/free` | Model identifier |
|
|
148
|
+
| `BUB_API_KEY` | — | Provider key (optional with `bub login openai`) |
|
|
149
|
+
| `BUB_API_BASE` | — | Custom provider endpoint |
|
|
150
|
+
| `BUB_API_FORMAT` | `completion` | `completion`, `responses`, or `messages` |
|
|
151
|
+
| `BUB_CLIENT_ARGS` | — | JSON object forwarded to the underlying model client |
|
|
152
|
+
| `BUB_MAX_STEPS` | `50` | Max tool-use loop iterations |
|
|
153
|
+
| `BUB_MAX_TOKENS` | `1024` | Max tokens per model call |
|
|
154
|
+
| `BUB_MODEL_TIMEOUT_SECONDS` | — | Model call timeout (seconds) |
|
|
155
|
+
|
|
156
|
+
## Background
|
|
157
|
+
|
|
158
|
+
Bub is shaped by one constraint: real collaboration is messier than a solo demo. In shared environments, operators need visible boundaries, auditable history, and extension points that do not collapse into framework sprawl.
|
|
159
|
+
|
|
160
|
+
Read more:
|
|
161
|
+
|
|
162
|
+
- [Why We Rewrote Bub](https://bub.build/posts/why-rewrite-bub/)
|
|
163
|
+
- [Socialized Evaluation and Agent Partnership](https://bub.build/posts/socialized-evaluation/)
|
|
164
|
+
- [Context from Tape](https://tape.systems)
|
|
165
|
+
|
|
166
|
+
## Docs
|
|
167
|
+
|
|
168
|
+
- [Getting Started](https://bub.build/docs/getting-started/) — install Bub and run the first turn
|
|
169
|
+
- [Architecture](https://bub.build/docs/concepts/architecture/) — the mental model behind the runtime
|
|
170
|
+
- [Channels](https://bub.build/docs/guides/channels/) — run Bub in CLI, Telegram, or your own channel
|
|
171
|
+
- [Skills](https://bub.build/docs/guides/skills/) — discover, inspect, and author Agent Skills in Bub
|
|
172
|
+
- [Extending](https://bub.build/docs/extending/) — write plugins, override hooks, ship tools and skills
|
|
173
|
+
- [Deployment](https://bub.build/docs/guides/deployment/) — Docker, environment, upgrades
|
|
174
|
+
|
|
175
|
+
## Development
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
make install
|
|
179
|
+
make check
|
|
180
|
+
make test
|
|
181
|
+
make docs
|
|
182
|
+
make docs-test
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
See [CONTRIBUTING.md](https://github.com/bubbuild/bub/blob/main/CONTRIBUTING.md).
|
|
186
|
+
|
|
187
|
+
## License
|
|
188
|
+
|
|
189
|
+
[Apache-2.0](https://github.com/bubbuild/bub/blob/main/LICENSE)
|
bub-0.3.7/README.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Bub
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
<picture>
|
|
6
|
+
<source srcset="https://raw.githubusercontent.com/bubbuild/bub/refs/heads/main/website/src/assets/bub-logo-dark.png" media="(prefers-color-scheme: dark)">
|
|
7
|
+
<img alt="Bub logo" src="https://raw.githubusercontent.com/bubbuild/bub/refs/heads/main/website/src/assets/bub-logo.png" width="200">
|
|
8
|
+
</picture>
|
|
9
|
+
|
|
10
|
+
<p><strong>A hook-first runtime for agents that live alongside people.</strong></p>
|
|
11
|
+
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
Bub is a small Python runtime for building agents in shared environments. It started in group chats, where multiple humans and agents had to work in the same conversation without hidden state, hand-wavy memory, or framework-specific magic.
|
|
15
|
+
|
|
16
|
+
Built on [agents.md](https://agents.md/) and [Agent Skills](https://agentskills.io/) , Bub stays intentionally small. Every turn stage is a [pluggy](https://pluggy.readthedocs.io/) hook. Builtins are included but replaceable. The same runtime drives CLI, Telegram, and any channel you add.
|
|
17
|
+
|
|
18
|
+
[Website](https://bub.build) · [GitHub](https://github.com/bubbuild/bub)
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install bub
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Or from source:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
git clone https://github.com/bubbuild/bub.git
|
|
30
|
+
cd bub
|
|
31
|
+
uv sync # enough to run Bub from source
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
For local development, use `make install` instead so the website toolchain and `prek` hooks are installed too.
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
uv run bub chat # interactive session
|
|
38
|
+
uv run bub run "summarize this repo" # one-shot task
|
|
39
|
+
uv run bub gateway # channel listener mode
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Why Bub
|
|
43
|
+
|
|
44
|
+
- **Hook-first runtime.** Every turn stage is a hook. Override one stage or replace the whole flow without forking the runtime.
|
|
45
|
+
- **Tape context.** Context is rebuilt from append-only records, not carried around as mutable session state. Easier to inspect, replay, and hand off.
|
|
46
|
+
- **One runtime across surfaces.** The same inbound pipeline runs across CLI, Telegram, and custom channels. Adapters change the surface, not the runtime model.
|
|
47
|
+
- **Batteries included.** CLI, Telegram, tools, skills, and model execution ship with the core runtime. Use the defaults first, replace them later.
|
|
48
|
+
- **Operator equivalence.** Humans and agents work inside the same runtime boundaries, with the same evidence trail and handoff model. No hidden operator class.
|
|
49
|
+
|
|
50
|
+
## How It Works
|
|
51
|
+
|
|
52
|
+
Every inbound message goes through one turn pipeline. Each stage is a hook.
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
resolve_session → load_state → build_prompt → run_model
|
|
56
|
+
↓
|
|
57
|
+
dispatch_outbound ← render_outbound ← save_state
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Builtins are registered first. External plugins load after them. At runtime, later plugins take precedence. There are no framework-only shortcuts.
|
|
61
|
+
|
|
62
|
+
Key source files:
|
|
63
|
+
|
|
64
|
+
- Turn orchestrator: [`src/bub/framework.py`](https://github.com/bubbuild/bub/blob/main/src/bub/framework.py)
|
|
65
|
+
- Hook contract: [`src/bub/hookspecs.py`](https://github.com/bubbuild/bub/blob/main/src/bub/hookspecs.py)
|
|
66
|
+
- Builtin hooks: [`src/bub/builtin/hook_impl.py`](https://github.com/bubbuild/bub/blob/main/src/bub/builtin/hook_impl.py)
|
|
67
|
+
- Skill discovery: [`src/bub/skills.py`](https://github.com/bubbuild/bub/blob/main/src/bub/skills.py)
|
|
68
|
+
|
|
69
|
+
## Extend It
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from bub import hookimpl
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class EchoPlugin:
|
|
76
|
+
@hookimpl
|
|
77
|
+
def build_prompt(self, message, session_id, state):
|
|
78
|
+
return f"[echo] {message['content']}"
|
|
79
|
+
|
|
80
|
+
@hookimpl
|
|
81
|
+
async def run_model(self, prompt, session_id, state):
|
|
82
|
+
return prompt
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
```toml
|
|
86
|
+
[project.entry-points."bub"]
|
|
87
|
+
echo = "my_package.plugin:EchoPlugin"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
See the [Extending docs](https://bub.build/docs/extending/) for hook guides, packaging, and plugin structure.
|
|
91
|
+
|
|
92
|
+
## CLI
|
|
93
|
+
|
|
94
|
+
| Command | Description |
|
|
95
|
+
| ------------------ | --------------------------------- |
|
|
96
|
+
| `bub chat` | Interactive REPL |
|
|
97
|
+
| `bub run MESSAGE` | One-shot turn |
|
|
98
|
+
| `bub gateway` | Channel listener (Telegram, etc.) |
|
|
99
|
+
| `bub install` | Install or sync Bub plugin deps |
|
|
100
|
+
| `bub update` | Upgrade Bub plugin deps |
|
|
101
|
+
| `bub login openai` | OpenAI Codex OAuth |
|
|
102
|
+
|
|
103
|
+
Lines starting with `,` enter internal command mode (`,help`, `,skill name=my-skill`, `,fs.read path=README.md`).
|
|
104
|
+
|
|
105
|
+
`bub hooks` still exists for diagnostics, but it is hidden from top-level help. `bub install` and `bub update` manage a separate uv project for Bub plugins, defaulting to `~/.bub/bub-project` or `BUB_PROJECT`.
|
|
106
|
+
|
|
107
|
+
## Configuration
|
|
108
|
+
|
|
109
|
+
| Variable | Default | Description |
|
|
110
|
+
| --------------------------- | ---------------------------- | ---------------------------------------------------- |
|
|
111
|
+
| `BUB_MODEL` | `openrouter:openrouter/free` | Model identifier |
|
|
112
|
+
| `BUB_API_KEY` | — | Provider key (optional with `bub login openai`) |
|
|
113
|
+
| `BUB_API_BASE` | — | Custom provider endpoint |
|
|
114
|
+
| `BUB_API_FORMAT` | `completion` | `completion`, `responses`, or `messages` |
|
|
115
|
+
| `BUB_CLIENT_ARGS` | — | JSON object forwarded to the underlying model client |
|
|
116
|
+
| `BUB_MAX_STEPS` | `50` | Max tool-use loop iterations |
|
|
117
|
+
| `BUB_MAX_TOKENS` | `1024` | Max tokens per model call |
|
|
118
|
+
| `BUB_MODEL_TIMEOUT_SECONDS` | — | Model call timeout (seconds) |
|
|
119
|
+
|
|
120
|
+
## Background
|
|
121
|
+
|
|
122
|
+
Bub is shaped by one constraint: real collaboration is messier than a solo demo. In shared environments, operators need visible boundaries, auditable history, and extension points that do not collapse into framework sprawl.
|
|
123
|
+
|
|
124
|
+
Read more:
|
|
125
|
+
|
|
126
|
+
- [Why We Rewrote Bub](https://bub.build/posts/why-rewrite-bub/)
|
|
127
|
+
- [Socialized Evaluation and Agent Partnership](https://bub.build/posts/socialized-evaluation/)
|
|
128
|
+
- [Context from Tape](https://tape.systems)
|
|
129
|
+
|
|
130
|
+
## Docs
|
|
131
|
+
|
|
132
|
+
- [Getting Started](https://bub.build/docs/getting-started/) — install Bub and run the first turn
|
|
133
|
+
- [Architecture](https://bub.build/docs/concepts/architecture/) — the mental model behind the runtime
|
|
134
|
+
- [Channels](https://bub.build/docs/guides/channels/) — run Bub in CLI, Telegram, or your own channel
|
|
135
|
+
- [Skills](https://bub.build/docs/guides/skills/) — discover, inspect, and author Agent Skills in Bub
|
|
136
|
+
- [Extending](https://bub.build/docs/extending/) — write plugins, override hooks, ship tools and skills
|
|
137
|
+
- [Deployment](https://bub.build/docs/guides/deployment/) — Docker, environment, upgrades
|
|
138
|
+
|
|
139
|
+
## Development
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
make install
|
|
143
|
+
make check
|
|
144
|
+
make test
|
|
145
|
+
make docs
|
|
146
|
+
make docs-test
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
See [CONTRIBUTING.md](https://github.com/bubbuild/bub/blob/main/CONTRIBUTING.md).
|
|
150
|
+
|
|
151
|
+
## License
|
|
152
|
+
|
|
153
|
+
[Apache-2.0](https://github.com/bubbuild/bub/blob/main/LICENSE)
|
|
@@ -24,6 +24,7 @@ dependencies = [
|
|
|
24
24
|
"pydantic-settings>=2.0.0",
|
|
25
25
|
"pyyaml>=6.0.0",
|
|
26
26
|
"pluggy>=1.6.0",
|
|
27
|
+
"inquirer-textual>=0.5.1",
|
|
27
28
|
"typer>=0.9.0",
|
|
28
29
|
"republic>=0.5.4",
|
|
29
30
|
"any-llm-sdk[anthropic]",
|
|
@@ -33,6 +34,7 @@ dependencies = [
|
|
|
33
34
|
"loguru>=0.7.2",
|
|
34
35
|
"rapidfuzz>=3.14.3",
|
|
35
36
|
"aiohttp>=3.13.3",
|
|
37
|
+
"httpx[socks]>=0.28.1",
|
|
36
38
|
]
|
|
37
39
|
|
|
38
40
|
[project.urls]
|
|
@@ -55,10 +57,6 @@ dev = [
|
|
|
55
57
|
"types-PyYAML>=6.0.12",
|
|
56
58
|
"mypy>=0.991",
|
|
57
59
|
"ruff>=0.11.5",
|
|
58
|
-
"mkdocs>=1.4.2",
|
|
59
|
-
"mkdocs-terminal>=4.7.0",
|
|
60
|
-
"mkdocstrings[python]>=0.26.1",
|
|
61
|
-
"rust-just>=1.42.0",
|
|
62
60
|
"prek>=0.3.1",
|
|
63
61
|
"pytest-asyncio>=1.3.0",
|
|
64
62
|
]
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""Bub framework package."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from importlib import import_module
|
|
7
|
+
from importlib.metadata import PackageNotFoundError
|
|
8
|
+
from importlib.metadata import version as metadata_version
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import TYPE_CHECKING
|
|
11
|
+
|
|
12
|
+
from bub.configure import Settings, config, ensure_config
|
|
13
|
+
from bub.framework import DEFAULT_HOME, BubFramework
|
|
14
|
+
from bub.hookspecs import hookimpl
|
|
15
|
+
from bub.tools import tool
|
|
16
|
+
|
|
17
|
+
__all__ = ["BubFramework", "Settings", "config", "ensure_config", "home", "hookimpl", "tool"]
|
|
18
|
+
|
|
19
|
+
try:
|
|
20
|
+
__version__ = import_module("bub._version").version
|
|
21
|
+
except ModuleNotFoundError:
|
|
22
|
+
try:
|
|
23
|
+
__version__ = metadata_version("bub")
|
|
24
|
+
except PackageNotFoundError:
|
|
25
|
+
__version__ = "0.0.0"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
home: Path
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def __getattr__(name: str):
|
|
33
|
+
if name == "home":
|
|
34
|
+
if "BUB_HOME" in os.environ:
|
|
35
|
+
return Path(os.environ["BUB_HOME"])
|
|
36
|
+
return DEFAULT_HOME
|
|
37
|
+
raise AttributeError(f"module {__name__} has no attribute {name}")
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.3.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 3,
|
|
21
|
+
__version__ = version = '0.3.7'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 3, 7)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -56,12 +56,14 @@ class Agent:
|
|
|
56
56
|
|
|
57
57
|
@cached_property
|
|
58
58
|
def tapes(self) -> TapeService:
|
|
59
|
+
import bub
|
|
60
|
+
|
|
59
61
|
tape_store = self.framework.get_tape_store()
|
|
60
62
|
if tape_store is None:
|
|
61
63
|
tape_store = InMemoryTapeStore()
|
|
62
64
|
tape_store = ForkTapeStore(tape_store)
|
|
63
65
|
llm = _build_llm(self.settings, tape_store, self.framework.build_tape_context())
|
|
64
|
-
return TapeService(llm,
|
|
66
|
+
return TapeService(llm, bub.home / "tapes", tape_store)
|
|
65
67
|
|
|
66
68
|
@staticmethod
|
|
67
69
|
def _events_from_iterable(iterable: Iterable) -> AsyncStreamEvents:
|
|
@@ -16,11 +16,23 @@ from urllib.request import url2pathname
|
|
|
16
16
|
|
|
17
17
|
import typer
|
|
18
18
|
|
|
19
|
+
from bub import __version__, configure
|
|
19
20
|
from bub.builtin.auth import app as login_app # noqa: F401
|
|
20
21
|
from bub.channels.message import ChannelMessage
|
|
21
22
|
from bub.envelope import field_of
|
|
22
23
|
from bub.framework import BubFramework
|
|
23
24
|
|
|
25
|
+
ONBOARD_BANNER = r"""
|
|
26
|
+
███████████ █████
|
|
27
|
+
▒▒███▒▒▒▒▒███ ▒▒███
|
|
28
|
+
▒███ ▒███ █████ ████ ▒███████
|
|
29
|
+
▒██████████ ▒▒███ ▒███ ▒███▒▒███
|
|
30
|
+
▒███▒▒▒▒▒███ ▒███ ▒███ ▒███ ▒███
|
|
31
|
+
▒███ ▒███ ▒███ ▒███ ▒███ ▒███
|
|
32
|
+
███████████ ▒▒████████ ████████
|
|
33
|
+
▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒ v{version}
|
|
34
|
+
""".strip("\n")
|
|
35
|
+
|
|
24
36
|
|
|
25
37
|
def run(
|
|
26
38
|
ctx: typer.Context,
|
|
@@ -92,6 +104,25 @@ def chat(
|
|
|
92
104
|
asyncio.run(manager.listen_and_run())
|
|
93
105
|
|
|
94
106
|
|
|
107
|
+
def onboard(ctx: typer.Context) -> None:
|
|
108
|
+
"""Interactively collect plugin configuration and write it to Bub's config file."""
|
|
109
|
+
|
|
110
|
+
framework = ctx.ensure_object(BubFramework)
|
|
111
|
+
typer.echo(ONBOARD_BANNER.format(version=__version__))
|
|
112
|
+
typer.echo("\nWelcome to Bub! Let's get you set up.\n")
|
|
113
|
+
|
|
114
|
+
try:
|
|
115
|
+
config_data = framework.collect_onboard_config()
|
|
116
|
+
configure.save(framework.config_file, config_data)
|
|
117
|
+
except (typer.Abort, typer.Exit):
|
|
118
|
+
raise
|
|
119
|
+
except Exception as exc:
|
|
120
|
+
typer.secho(f"Onboarding failed: {exc}", err=True, fg="red")
|
|
121
|
+
raise typer.Exit(1) from exc
|
|
122
|
+
|
|
123
|
+
typer.echo(f"Saved config to {framework.config_file}")
|
|
124
|
+
|
|
125
|
+
|
|
95
126
|
@lru_cache(maxsize=1)
|
|
96
127
|
def _find_uv() -> str:
|
|
97
128
|
import shutil
|
|
@@ -106,10 +137,9 @@ def _find_uv() -> str:
|
|
|
106
137
|
|
|
107
138
|
@lru_cache(maxsize=1)
|
|
108
139
|
def _default_project() -> Path:
|
|
109
|
-
|
|
140
|
+
import bub
|
|
110
141
|
|
|
111
|
-
|
|
112
|
-
project = settings.home / "bub-project"
|
|
142
|
+
project = bub.home / "bub-project"
|
|
113
143
|
project.mkdir(exist_ok=True, parents=True)
|
|
114
144
|
return project
|
|
115
145
|
|