Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 15 additions & 34 deletions .tests/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,49 +23,30 @@ check_lines_in_file() {
if [ -n "$REBOOT_WHL_FILE" ]; then
# Install the `reboot` package from the specified path
# explicitly, overwriting the version from `pyproject.toml`.
rye remove --no-sync reboot
rye remove --no-sync --dev reboot
rye add --dev reboot --absolute --path="${SANDBOX_ROOT}$REBOOT_WHL_FILE"
uv add --no-sync "${SANDBOX_ROOT}$REBOOT_WHL_FILE"
fi

# Force a fresh virtualenv. A pre-existing `.venv/` (e.g.,
# carried over from a pre-baked image, or copied between
# containers/host paths during the dev-container test) will
# have absolute shebangs in its console scripts (`rbt`,
# `pytest`) pointing at the path where it was originally
# created, which produces "bad interpreter: No such file or
# directory" when those scripts are executed from a different
# location. `rye sync` only regenerates entry-point scripts
# for packages it reinstalls, so it can't repair an existing
# venv whose shebangs are stale. Nuking and re-syncing here
# guarantees the venv lives at the current path.
# Force a fresh virtualenv. A pre-existing `.venv/` (e.g., carried
# over from a pre-baked image, or copied between containers/host
# paths during the dev-container test) has its original creation
# path baked into its `activate` script and console-script
# shebangs, which breaks them when the venv is used from a
# different location. `uv sync` only regenerates entry-point
# scripts for packages it reinstalls, so it can't repair a
# relocated venv. Nuking and re-syncing guarantees the venv lives
# at the current path, which makes it safe to `activate`.
rm -rf .venv
rye sync --no-lock

# Don't `source .venv/bin/activate`: that script bakes in the
# venv's original creation path on its first line, which is
# wrong when the venv has been relocated (e.g., a pre-baked
# image bind-mounted at a different path in CI). The
# console-script wrappers (`rbt`, `pytest`) also have absolute
# shebangs that point at the stale path. Set `PATH` and
# `VIRTUAL_ENV` to the real location ourselves, and invoke the
# tools via `python -m`: the `python` symlink resolves the
# venv from its own location through `pyvenv.cfg`, so it
# survives relocation, and `-m` bypasses the broken script
# shebangs.
VENV_BIN="$(pwd)/.venv/bin"
export PATH="$VENV_BIN:$PATH"
export VIRTUAL_ENV="$(pwd)/.venv"
PYTHON="$VENV_BIN/python"
uv sync
source .venv/bin/activate

# When running in a Bazel test, our `.rbtrc` file ends up in a
# very deep directory structure, which can result in "path too
# long" errors from RocksDB. Explicitly specify a shorter path.
RBT_FLAGS="--state-directory=$(mktemp -d)"

"$PYTHON" -m reboot.cli.rbt_main $RBT_FLAGS generate
rbt $RBT_FLAGS generate

"$PYTHON" -m pytest backend/
pytest backend/

if [ -n "$EXPECTED_RBT_DEV_OUTPUT_FILE" ]; then
actual_output_file=$(mktemp)
Expand All @@ -86,7 +67,7 @@ if [ -n "$EXPECTED_RBT_DEV_OUTPUT_FILE" ]; then
# are made: the health check terminates the process before any
# transcript ingestion happens.
ANTHROPIC_API_KEY="dummy-for-health-check" \
"$PYTHON" -m reboot.cli.rbt_main $RBT_FLAGS dev run \
rbt $RBT_FLAGS dev run \
--config=dist \
--terminate-after-health-check \
> "$actual_output_file"
Expand Down
14 changes: 9 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,22 @@
# locally before `docker build` so that `web/dist/` contains the
# bundled UIs. This image copies that prebuilt bundle rather
# than installing Node and rebuilding it here.
FROM ghcr.io/reboot-dev/reboot-base:1.1.0
FROM ghcr.io/reboot-dev/reboot-base:1.2.0

WORKDIR /app

# Install Python dependencies from the rye-generated lockfile.
# `pip` accepts the `requirements.lock` format directly. This
# Install Python dependencies from the uv lockfile. `pip` can't
# read `uv.lock` directly, so `uv` exports it to
# `requirements.txt` format, which `pip` accepts. This
# layer is cached until the lockfile changes, so app-code edits
# don't trigger a re-install of the dependency tree. The base
# image already includes Reboot itself; the lockfile pins it to
# the matching version.
COPY requirements.lock requirements.txt
RUN pip install -r requirements.txt
COPY --from=ghcr.io/astral-sh/uv:0.11.13 /uv /usr/local/bin/uv
COPY pyproject.toml uv.lock ./
RUN uv export --frozen --no-dev --no-emit-project \
--format requirements-txt -o requirements.txt \
&& pip install -r requirements.txt

# Copy the API definition and `.rbtrc`, then generate Reboot
# code. Separate layer so regeneration only reruns when the
Expand Down
39 changes: 17 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,13 @@ for manual fix-ups).

```bash
# Install Python dependencies and create the virtualenv.
rye sync
source .venv/bin/activate
uv sync

# Install web dependencies.
cd web && npm install && cd ..

# Generate API code (Python + React bindings).
rbt generate
uv run rbt generate

# Build the React UIs.
cd web && npm run build && cd ..
Expand All @@ -99,7 +98,7 @@ When deployed to Reboot Cloud, store the key as a Reboot
secret instead:

```bash
rbt cloud secret set --application-name=agent-wiki ANTHROPIC_API_KEY=sk-ant-...
uv run rbt cloud secret set --application-name=agent-wiki ANTHROPIC_API_KEY=sk-ant-...
```

Cloud injects each secret into the application's environment
Expand All @@ -108,21 +107,24 @@ is what the Anthropic SDK reads directly — the same code works
in both places.

Then run the app (each command in its own terminal, from the
project directory, with `.venv` activated):
project directory):

```bash
# Terminal 1: start the Reboot backend.
rbt dev run
uv run rbt dev run

# Terminal 2: start the Vite dev server for Hot Module Replacement.
cd web && npm run dev
```

Then open <http://localhost:9991> and follow the setup wizard to
connect a chat host (such as Claude or ChatGPT) to the app.

State persists between restarts under the name `agent-wiki`
(configured in `.rbtrc`). To wipe it:

```bash
rbt dev expunge --application-name=agent-wiki
uv run rbt dev expunge --application-name=agent-wiki
```

## Running the tests
Expand All @@ -133,24 +135,17 @@ making any real Anthropic calls (the LLM is replaced by a
scripted Pydantic AI `FunctionModel`).

```bash
rye sync
source .venv/bin/activate
pytest backend/
uv sync
uv run pytest backend/
```

## Testing with MCPJam Inspector

`mcp_servers.json` is pre-configured. In another terminal:

```bash
npx @mcpjam/inspector@2.9.3 --config mcp_servers.json --server agent-wiki
```
## Try it out

Try these prompts to exercise each capability. The librarian
works asynchronously, so after an `add_transcript` call watch
the backend log for `librarian[...] tool call ...` lines to see
it read the wiki, decide where material belongs, and rewrite
pages.
From the connected chat host, try these prompts to exercise
each capability. The librarian works asynchronously, so after
an `add_transcript` call watch the backend log for
`librarian[...] tool call ...` lines to see it read the wiki,
decide where material belongs, and rewrite pages.

1. `Create a wiki called "Team Knowledge Base" about
engineering runbooks.` — exercises `create_wiki`, which
Expand Down
13 changes: 6 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@ dependencies = [
"uuid7>=0.1.0",
"anyio>=4.0.0",
"pydantic-ai-slim[anthropic]>=1.0.0",
"reboot==1.1.0",
"reboot==1.2.0",
]

[tool.rye]
dev-dependencies = [
[dependency-groups]
dev = [
"pytest>=7.4",
"reboot==1.1.0",
]

# This project only uses `rye` to provide `python` and its dependencies.
virtual = true
managed = true
# There is no `[build-system]` table: that tells `uv` this is a virtual
# (non-package) project — it installs the dependencies into `.venv` but
# never tries to build/install the project itself.
Loading
Loading