llm-tool-brave 0.9.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.
- llm_tool_brave-0.9.0/.github/workflows/publish.yml +60 -0
- llm_tool_brave-0.9.0/.github/workflows/test.yml +32 -0
- llm_tool_brave-0.9.0/.gitignore +12 -0
- llm_tool_brave-0.9.0/AGENTS.md +1 -0
- llm_tool_brave-0.9.0/PKG-INFO +205 -0
- llm_tool_brave-0.9.0/README.md +190 -0
- llm_tool_brave-0.9.0/TODO.md +11 -0
- llm_tool_brave-0.9.0/llm_tool_brave.py +710 -0
- llm_tool_brave-0.9.0/pyproject.toml +42 -0
- llm_tool_brave-0.9.0/tests/test_llm_tool_brave.py +268 -0
- llm_tool_brave-0.9.0/uv.lock +1006 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
release:
|
|
6
|
+
types: [published]
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
id-token: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
matrix:
|
|
17
|
+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v5
|
|
21
|
+
|
|
22
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
23
|
+
uses: actions/setup-python@v6
|
|
24
|
+
with:
|
|
25
|
+
python-version: ${{ matrix.python-version }}
|
|
26
|
+
|
|
27
|
+
- name: Set up uv
|
|
28
|
+
uses: astral-sh/setup-uv@v6
|
|
29
|
+
with:
|
|
30
|
+
enable-cache: true
|
|
31
|
+
|
|
32
|
+
- name: Install dependencies
|
|
33
|
+
run: uv sync --locked --all-groups
|
|
34
|
+
|
|
35
|
+
- name: Run tests
|
|
36
|
+
run: uv run pytest
|
|
37
|
+
|
|
38
|
+
publish:
|
|
39
|
+
runs-on: ubuntu-latest
|
|
40
|
+
needs: [test]
|
|
41
|
+
environment: pypi
|
|
42
|
+
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@v5
|
|
45
|
+
|
|
46
|
+
- name: Set up Python
|
|
47
|
+
uses: actions/setup-python@v6
|
|
48
|
+
with:
|
|
49
|
+
python-version: "3.x"
|
|
50
|
+
|
|
51
|
+
- name: Set up uv
|
|
52
|
+
uses: astral-sh/setup-uv@v6
|
|
53
|
+
with:
|
|
54
|
+
enable-cache: true
|
|
55
|
+
|
|
56
|
+
- name: Build
|
|
57
|
+
run: uv build
|
|
58
|
+
|
|
59
|
+
- name: Publish to PyPI
|
|
60
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Test
|
|
2
|
+
|
|
3
|
+
on: [push, pull_request]
|
|
4
|
+
|
|
5
|
+
permissions:
|
|
6
|
+
contents: read
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
matrix:
|
|
13
|
+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v5
|
|
17
|
+
|
|
18
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
19
|
+
uses: actions/setup-python@v6
|
|
20
|
+
with:
|
|
21
|
+
python-version: ${{ matrix.python-version }}
|
|
22
|
+
|
|
23
|
+
- name: Set up uv
|
|
24
|
+
uses: astral-sh/setup-uv@v6
|
|
25
|
+
with:
|
|
26
|
+
enable-cache: true
|
|
27
|
+
|
|
28
|
+
- name: Install dependencies
|
|
29
|
+
run: uv sync --locked --all-groups
|
|
30
|
+
|
|
31
|
+
- name: Run tests
|
|
32
|
+
run: uv run pytest
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
README.md
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: llm-tool-brave
|
|
3
|
+
Version: 0.9.0
|
|
4
|
+
Summary: brave Search API tool for Simon Willison's LLM
|
|
5
|
+
Project-URL: Homepage, https://github.com/rdslw/llm-tool-brave
|
|
6
|
+
Project-URL: Changelog, https://github.com/rdslw/llm-tool-brave/releases
|
|
7
|
+
Project-URL: Issues, https://github.com/rdslw/llm-tool-brave/issues
|
|
8
|
+
Project-URL: CI, https://github.com/rdslw/llm-tool-brave/actions
|
|
9
|
+
Author: llm-tool-brave contributors, Radoslaw Stachowiak
|
|
10
|
+
License-Expression: Apache-2.0
|
|
11
|
+
Keywords: brave,llm,llm-plugin,search,web-search
|
|
12
|
+
Requires-Python: >=3.9
|
|
13
|
+
Requires-Dist: llm>=0.27
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# llm-tool-brave
|
|
17
|
+
|
|
18
|
+
brave Search API plugin/tool for [Simon Willison's LLM](https://llm.datasette.io/).
|
|
19
|
+
|
|
20
|
+
Default api method: `context`, backed by brave's LLM Context API.
|
|
21
|
+
It returns pre-extracted, token-budgeted grounding content for the model running in `llm`.
|
|
22
|
+
**NB:** This plugin does **not** shell out to `bx`;
|
|
23
|
+
it calls `https://api.search.brave.com/res/v1` directly with the Python standard library.
|
|
24
|
+
|
|
25
|
+
`AGENTS.md` points at this file, so keep operational project knowledge here.
|
|
26
|
+
|
|
27
|
+
## Quick Start
|
|
28
|
+
|
|
29
|
+
### Quick in-place usage
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
uv sync # see explanation below
|
|
33
|
+
uv run pytest # optional
|
|
34
|
+
uv run llm plugins # shall show llm-tool-brave
|
|
35
|
+
uv run llm tools list | grep -E '^ +brave'
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`uv sync` installs this package into `.venv` because `[tool.uv] package = true`.
|
|
39
|
+
The default `dev` dependency group makes `uv run pytest` work without extra flags.
|
|
40
|
+
|
|
41
|
+
Runtime-only local check:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
uv run --no-dev llm plugins
|
|
45
|
+
uv run --no-dev llm tools list | grep brave
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Install into a global `llm` environment from local dir:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
llm install -e .
|
|
52
|
+
llm plugins
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Install into a global `llm` after PyPi publishing:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
llm install llm-tool-brave
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Configuration (one-time)
|
|
62
|
+
|
|
63
|
+
Set a brave Search API key:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
llm keys set brave
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Lookup order: stored key alias `brave`, `brave-search`, then env BRAVE_SEARCH_API_KEY.
|
|
70
|
+
|
|
71
|
+
Avoid raw API keys in toolbox constructor arguments. LLM may log those; `llm keys`
|
|
72
|
+
or `BRAVE_SEARCH_API_KEY` keeps secrets out of prompts and tool-call logs.
|
|
73
|
+
|
|
74
|
+
## Usage
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# default: only context tool is enabled; --td optional: shows tools calls by llm
|
|
78
|
+
llm -T Brave --td 'Search current web context for the latest llm tool plugin documentation and summarize it.'
|
|
79
|
+
|
|
80
|
+
# selected tools
|
|
81
|
+
llm -T 'Brave("context,web,news")' 'Find current uv release notes and summarize the important changes.'
|
|
82
|
+
|
|
83
|
+
# all implemented endpoints
|
|
84
|
+
llm -T 'Brave("all")' 'Find coffee shops near Warsaw city center and summarize the options.'
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Tools
|
|
88
|
+
|
|
89
|
+
| Tool | Endpoint | Plan | Use |
|
|
90
|
+
| --- | --- | --- | --- |
|
|
91
|
+
| `context` | `/llm/context` | Search | Main RAG/LLM grounding tool with extracted text chunks, tables, code, and source metadata. |
|
|
92
|
+
| `web` | `/web/search` | Search | Traditional web results with URLs, snippets, and rich result types. |
|
|
93
|
+
| `news` | `/news/search` | Search | Recent news with freshness filters. |
|
|
94
|
+
| `images` | `/images/search` | Search | Image results and thumbnails. |
|
|
95
|
+
| `videos` | `/videos/search` | Search | Video metadata. |
|
|
96
|
+
| `places` | `/local/place_search` | Search | Businesses, landmarks, POIs, cities, and addresses. |
|
|
97
|
+
| `suggest` | `/suggest/search` | Suggest | Query autocomplete and rich entity suggestions. |
|
|
98
|
+
| `spellcheck` | `/spellcheck/search` | Spellcheck | Pre-search query correction. |
|
|
99
|
+
| `answers` | `/chat/completions` | Answers | brave-generated answer. Prefer `context` when your current LLM should synthesize. |
|
|
100
|
+
|
|
101
|
+
Enable selected tools with `Brave("context,web,news")`; enable all with
|
|
102
|
+
`Brave("all")`.
|
|
103
|
+
|
|
104
|
+
## Context Tool
|
|
105
|
+
|
|
106
|
+
Use `brave_context` first for web research, docs lookup, fact-checking, and RAG.
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
llm -T Brave --td 'Use brave context to find Python 3.13 pathlib changes and explain the practical impact.'
|
|
110
|
+
llm -T Brave --td 'Use brave context, restricted to docs.python.org and peps.python.org, to answer: what changed in Python 3.13 typing?'
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
| Parameter | brave API field | Default | Range / values |
|
|
114
|
+
| --- | --- | --- | --- |
|
|
115
|
+
| `query` | `q` | required | search query |
|
|
116
|
+
| `max_tokens` | `maximum_number_of_tokens` | `8192` | `1024-32768` |
|
|
117
|
+
| `max_urls` | `maximum_number_of_urls` | `20` | `1-50` |
|
|
118
|
+
| `max_snippets` | `maximum_number_of_snippets` | `50` | `1-100` |
|
|
119
|
+
| `max_tokens_per_url` | `maximum_number_of_tokens_per_url` | `4096` | `512-8192` |
|
|
120
|
+
| `max_snippets_per_url` | `maximum_number_of_snippets_per_url` | `50` | `1-100` |
|
|
121
|
+
| `threshold` | `context_threshold_mode` | `balanced` | `strict`, `balanced`, `lenient`, `disabled` |
|
|
122
|
+
| `freshness` | `freshness` | none | `pd`, `pw`, `pm`, `py`, or `YYYY-MM-DDtoYYYY-MM-DD` |
|
|
123
|
+
| `include_sites`, `exclude_sites`, `goggles` | `goggles` | none | inline brave Goggles rules |
|
|
124
|
+
| `lat`, `long`, `city`, `state`, `loc_country`, `postal_code` | location headers | none | location hints |
|
|
125
|
+
|
|
126
|
+
Additional params: `country` (`US`), `search_lang` (`en`), `count` (`20`, `1-50`), `spellcheck` (`true`), `enable_local` (none).
|
|
127
|
+
|
|
128
|
+
Each call is bounded by `max_tokens` before returning to `llm`. Multiple searches
|
|
129
|
+
consume multiple tool responses plus JSON/source metadata. Invalid documented brave
|
|
130
|
+
ranges are rejected before the API request.
|
|
131
|
+
|
|
132
|
+
## Untrusted Web Content
|
|
133
|
+
|
|
134
|
+
Search result text is external and untrusted. The plugin wraps snippets and
|
|
135
|
+
descriptions with compact `BRAVE_UNTRUSTED_CONTENT` markers and adds one
|
|
136
|
+
`security_notice` field. URLs, titles, source metadata, and structured fields stay
|
|
137
|
+
intact.
|
|
138
|
+
|
|
139
|
+
This is a prompt-level guardrail, not a security boundary. Be careful combining
|
|
140
|
+
search tools with tools that can read private data, execute commands, send messages,
|
|
141
|
+
or exfiltrate information.
|
|
142
|
+
|
|
143
|
+
## Python API
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
import llm
|
|
147
|
+
from llm_tool_brave import Brave
|
|
148
|
+
|
|
149
|
+
model = llm.get_model("gpt-5.4-mini")
|
|
150
|
+
response = model.chain(
|
|
151
|
+
"Use brave context to find the current LLM tool plugin docs and summarize the API shape.",
|
|
152
|
+
tools=[Brave()],
|
|
153
|
+
)
|
|
154
|
+
print(response.text())
|
|
155
|
+
|
|
156
|
+
tools = [Brave("context,web,news")]
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Build And Release
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
uv build
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Publishing uses `.github/workflows/publish.yml`: full Python test matrix, `uv build`,
|
|
166
|
+
then PyPI Trusted Publishing. Before the first release, configure PyPI for repository
|
|
167
|
+
`rdslw/llm-tool-brave`, workflow `publish.yml`, environment `pypi`.
|
|
168
|
+
|
|
169
|
+
Release:
|
|
170
|
+
|
|
171
|
+
1. Update `version` in `pyproject.toml`. PyPI versions are immutable.
|
|
172
|
+
2. Run `uv sync --locked --all-groups`, `uv run pytest`, and `uv build`.
|
|
173
|
+
3. Commit, tag, push, then create a GitHub release from that tag.
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
git add pyproject.toml
|
|
177
|
+
git commit -m "Release 0.1.0"
|
|
178
|
+
git tag -a 0.1.0 -m "Release 0.1.0"
|
|
179
|
+
git push origin master
|
|
180
|
+
git push origin 0.1.0
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
The release event triggers `Publish to PyPI`. `workflow_dispatch` is available for
|
|
184
|
+
manual publishing, but normal versions should publish from release tags.
|
|
185
|
+
|
|
186
|
+
Post-publish smoke test:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
uvx --from llm llm install llm-tool-brave
|
|
190
|
+
llm plugins
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Direct API Calls vs. `bx`
|
|
194
|
+
|
|
195
|
+
This plugin manually constructs HTTPS requests to the brave Search API instead of
|
|
196
|
+
invoking `bx`. Tradeoffs:
|
|
197
|
+
|
|
198
|
+
1. **Packaging:** direct API calls avoid requiring a separate `bx` binary.
|
|
199
|
+
2. **LLM ergonomics:** direct Python methods expose cleaner structured tool schemas.
|
|
200
|
+
3. **Secrets:** direct `llm keys` / `BRAVE_SEARCH_API_KEY` integration avoids command-line API keys.
|
|
201
|
+
4. **Feature coverage:** `bx` may expose brave API features, flags, config, and workflows not implemented here.
|
|
202
|
+
5. **Errors:** direct calls return structured tool errors; `bx` has mature CLI exit codes and diagnostics.
|
|
203
|
+
6. **Performance/control:** direct HTTP avoids subprocess and shell quoting overhead, but this plugin owns request/response behavior.
|
|
204
|
+
7. **API changes:** because `bx` is developed by brave, it is more likely to pick up brave Search API changes quickly.
|
|
205
|
+
8. **Shared utility:** an installed `bx` CLI is also useful for humans, scripts, and other tools, and is easy to test directly.
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# llm-tool-brave
|
|
2
|
+
|
|
3
|
+
brave Search API plugin/tool for [Simon Willison's LLM](https://llm.datasette.io/).
|
|
4
|
+
|
|
5
|
+
Default api method: `context`, backed by brave's LLM Context API.
|
|
6
|
+
It returns pre-extracted, token-budgeted grounding content for the model running in `llm`.
|
|
7
|
+
**NB:** This plugin does **not** shell out to `bx`;
|
|
8
|
+
it calls `https://api.search.brave.com/res/v1` directly with the Python standard library.
|
|
9
|
+
|
|
10
|
+
`AGENTS.md` points at this file, so keep operational project knowledge here.
|
|
11
|
+
|
|
12
|
+
## Quick Start
|
|
13
|
+
|
|
14
|
+
### Quick in-place usage
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
uv sync # see explanation below
|
|
18
|
+
uv run pytest # optional
|
|
19
|
+
uv run llm plugins # shall show llm-tool-brave
|
|
20
|
+
uv run llm tools list | grep -E '^ +brave'
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`uv sync` installs this package into `.venv` because `[tool.uv] package = true`.
|
|
24
|
+
The default `dev` dependency group makes `uv run pytest` work without extra flags.
|
|
25
|
+
|
|
26
|
+
Runtime-only local check:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
uv run --no-dev llm plugins
|
|
30
|
+
uv run --no-dev llm tools list | grep brave
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Install into a global `llm` environment from local dir:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
llm install -e .
|
|
37
|
+
llm plugins
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Install into a global `llm` after PyPi publishing:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
llm install llm-tool-brave
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Configuration (one-time)
|
|
47
|
+
|
|
48
|
+
Set a brave Search API key:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
llm keys set brave
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Lookup order: stored key alias `brave`, `brave-search`, then env BRAVE_SEARCH_API_KEY.
|
|
55
|
+
|
|
56
|
+
Avoid raw API keys in toolbox constructor arguments. LLM may log those; `llm keys`
|
|
57
|
+
or `BRAVE_SEARCH_API_KEY` keeps secrets out of prompts and tool-call logs.
|
|
58
|
+
|
|
59
|
+
## Usage
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# default: only context tool is enabled; --td optional: shows tools calls by llm
|
|
63
|
+
llm -T Brave --td 'Search current web context for the latest llm tool plugin documentation and summarize it.'
|
|
64
|
+
|
|
65
|
+
# selected tools
|
|
66
|
+
llm -T 'Brave("context,web,news")' 'Find current uv release notes and summarize the important changes.'
|
|
67
|
+
|
|
68
|
+
# all implemented endpoints
|
|
69
|
+
llm -T 'Brave("all")' 'Find coffee shops near Warsaw city center and summarize the options.'
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Tools
|
|
73
|
+
|
|
74
|
+
| Tool | Endpoint | Plan | Use |
|
|
75
|
+
| --- | --- | --- | --- |
|
|
76
|
+
| `context` | `/llm/context` | Search | Main RAG/LLM grounding tool with extracted text chunks, tables, code, and source metadata. |
|
|
77
|
+
| `web` | `/web/search` | Search | Traditional web results with URLs, snippets, and rich result types. |
|
|
78
|
+
| `news` | `/news/search` | Search | Recent news with freshness filters. |
|
|
79
|
+
| `images` | `/images/search` | Search | Image results and thumbnails. |
|
|
80
|
+
| `videos` | `/videos/search` | Search | Video metadata. |
|
|
81
|
+
| `places` | `/local/place_search` | Search | Businesses, landmarks, POIs, cities, and addresses. |
|
|
82
|
+
| `suggest` | `/suggest/search` | Suggest | Query autocomplete and rich entity suggestions. |
|
|
83
|
+
| `spellcheck` | `/spellcheck/search` | Spellcheck | Pre-search query correction. |
|
|
84
|
+
| `answers` | `/chat/completions` | Answers | brave-generated answer. Prefer `context` when your current LLM should synthesize. |
|
|
85
|
+
|
|
86
|
+
Enable selected tools with `Brave("context,web,news")`; enable all with
|
|
87
|
+
`Brave("all")`.
|
|
88
|
+
|
|
89
|
+
## Context Tool
|
|
90
|
+
|
|
91
|
+
Use `brave_context` first for web research, docs lookup, fact-checking, and RAG.
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
llm -T Brave --td 'Use brave context to find Python 3.13 pathlib changes and explain the practical impact.'
|
|
95
|
+
llm -T Brave --td 'Use brave context, restricted to docs.python.org and peps.python.org, to answer: what changed in Python 3.13 typing?'
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
| Parameter | brave API field | Default | Range / values |
|
|
99
|
+
| --- | --- | --- | --- |
|
|
100
|
+
| `query` | `q` | required | search query |
|
|
101
|
+
| `max_tokens` | `maximum_number_of_tokens` | `8192` | `1024-32768` |
|
|
102
|
+
| `max_urls` | `maximum_number_of_urls` | `20` | `1-50` |
|
|
103
|
+
| `max_snippets` | `maximum_number_of_snippets` | `50` | `1-100` |
|
|
104
|
+
| `max_tokens_per_url` | `maximum_number_of_tokens_per_url` | `4096` | `512-8192` |
|
|
105
|
+
| `max_snippets_per_url` | `maximum_number_of_snippets_per_url` | `50` | `1-100` |
|
|
106
|
+
| `threshold` | `context_threshold_mode` | `balanced` | `strict`, `balanced`, `lenient`, `disabled` |
|
|
107
|
+
| `freshness` | `freshness` | none | `pd`, `pw`, `pm`, `py`, or `YYYY-MM-DDtoYYYY-MM-DD` |
|
|
108
|
+
| `include_sites`, `exclude_sites`, `goggles` | `goggles` | none | inline brave Goggles rules |
|
|
109
|
+
| `lat`, `long`, `city`, `state`, `loc_country`, `postal_code` | location headers | none | location hints |
|
|
110
|
+
|
|
111
|
+
Additional params: `country` (`US`), `search_lang` (`en`), `count` (`20`, `1-50`), `spellcheck` (`true`), `enable_local` (none).
|
|
112
|
+
|
|
113
|
+
Each call is bounded by `max_tokens` before returning to `llm`. Multiple searches
|
|
114
|
+
consume multiple tool responses plus JSON/source metadata. Invalid documented brave
|
|
115
|
+
ranges are rejected before the API request.
|
|
116
|
+
|
|
117
|
+
## Untrusted Web Content
|
|
118
|
+
|
|
119
|
+
Search result text is external and untrusted. The plugin wraps snippets and
|
|
120
|
+
descriptions with compact `BRAVE_UNTRUSTED_CONTENT` markers and adds one
|
|
121
|
+
`security_notice` field. URLs, titles, source metadata, and structured fields stay
|
|
122
|
+
intact.
|
|
123
|
+
|
|
124
|
+
This is a prompt-level guardrail, not a security boundary. Be careful combining
|
|
125
|
+
search tools with tools that can read private data, execute commands, send messages,
|
|
126
|
+
or exfiltrate information.
|
|
127
|
+
|
|
128
|
+
## Python API
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
import llm
|
|
132
|
+
from llm_tool_brave import Brave
|
|
133
|
+
|
|
134
|
+
model = llm.get_model("gpt-5.4-mini")
|
|
135
|
+
response = model.chain(
|
|
136
|
+
"Use brave context to find the current LLM tool plugin docs and summarize the API shape.",
|
|
137
|
+
tools=[Brave()],
|
|
138
|
+
)
|
|
139
|
+
print(response.text())
|
|
140
|
+
|
|
141
|
+
tools = [Brave("context,web,news")]
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Build And Release
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
uv build
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Publishing uses `.github/workflows/publish.yml`: full Python test matrix, `uv build`,
|
|
151
|
+
then PyPI Trusted Publishing. Before the first release, configure PyPI for repository
|
|
152
|
+
`rdslw/llm-tool-brave`, workflow `publish.yml`, environment `pypi`.
|
|
153
|
+
|
|
154
|
+
Release:
|
|
155
|
+
|
|
156
|
+
1. Update `version` in `pyproject.toml`. PyPI versions are immutable.
|
|
157
|
+
2. Run `uv sync --locked --all-groups`, `uv run pytest`, and `uv build`.
|
|
158
|
+
3. Commit, tag, push, then create a GitHub release from that tag.
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
git add pyproject.toml
|
|
162
|
+
git commit -m "Release 0.1.0"
|
|
163
|
+
git tag -a 0.1.0 -m "Release 0.1.0"
|
|
164
|
+
git push origin master
|
|
165
|
+
git push origin 0.1.0
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
The release event triggers `Publish to PyPI`. `workflow_dispatch` is available for
|
|
169
|
+
manual publishing, but normal versions should publish from release tags.
|
|
170
|
+
|
|
171
|
+
Post-publish smoke test:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
uvx --from llm llm install llm-tool-brave
|
|
175
|
+
llm plugins
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Direct API Calls vs. `bx`
|
|
179
|
+
|
|
180
|
+
This plugin manually constructs HTTPS requests to the brave Search API instead of
|
|
181
|
+
invoking `bx`. Tradeoffs:
|
|
182
|
+
|
|
183
|
+
1. **Packaging:** direct API calls avoid requiring a separate `bx` binary.
|
|
184
|
+
2. **LLM ergonomics:** direct Python methods expose cleaner structured tool schemas.
|
|
185
|
+
3. **Secrets:** direct `llm keys` / `BRAVE_SEARCH_API_KEY` integration avoids command-line API keys.
|
|
186
|
+
4. **Feature coverage:** `bx` may expose brave API features, flags, config, and workflows not implemented here.
|
|
187
|
+
5. **Errors:** direct calls return structured tool errors; `bx` has mature CLI exit codes and diagnostics.
|
|
188
|
+
6. **Performance/control:** direct HTTP avoids subprocess and shell quoting overhead, but this plugin owns request/response behavior.
|
|
189
|
+
7. **API changes:** because `bx` is developed by brave, it is more likely to pick up brave Search API changes quickly.
|
|
190
|
+
8. **Shared utility:** an installed `bx` CLI is also useful for humans, scripts, and other tools, and is easy to test directly.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
## List of TODO tasks for llm-tool-brave
|
|
2
|
+
|
|
3
|
+
* Based on llm-tool-brave create llm-tool-bx which will simply use 'bx' CLI tool instead of http api
|
|
4
|
+
- plan to be defined...
|
|
5
|
+
|
|
6
|
+
* Stage two untrusted-content hardening:
|
|
7
|
+
- add broader recursive coverage for all brave response fields that can contain external page text
|
|
8
|
+
- consider a fuller warning mode for fetched/full-page content if that endpoint is added later
|
|
9
|
+
- detect/log suspicious prompt-injection phrases for debugging without blocking legitimate results
|
|
10
|
+
- harden marker sanitization against homoglyph and zero-width spoofing patterns, following the fuller openclaw-style approach
|
|
11
|
+
- add compatibility tests using captured brave response fixtures for context, web, news, images, videos, and places
|