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
32 changes: 31 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Developer notes for working on ReactantServer.jl. For using the server, start with
[Getting Started](docs/src/manual/getting_started.md).

After cloning, instantiate the workspace (gRPCServer resolves from the `scelles-merge` tag of
After cloning, instantiate the workspace (gRPCServer resolves from the `main` branch of
github.com/csvance/gRPCServer.jl via the workspace `[sources]`):

```
Expand Down Expand Up @@ -120,6 +120,36 @@ the two stub files are hand-maintained:
`control_server_stubs.jl` and the `<Service>_<Rpc>_Client` constructors into
`control_client_stubs.jl`, preserving the hand-tuned deadlines already in those files.

## Kaimon gate tools (dev only)

`packages/ReactantServer/ext/KaimonGateExt.jl` registers four `rserver_*` GateTools with a running
[Kaimon](https://github.com/kahliburke/Kaimon.jl) gate, so an agent (or a REPL) can bring a worker
up in the session where the code is loaded: `rserver_start` (model directory, optional model
allowlist, `accelerator`, GPU `device`, ports), `rserver_status`, `rserver_models`, and
`rserver_stop`. KaimonGate is a weak dependency, nothing in `src/` references it, and a session
that never loads it pays nothing. This is a development surface; deployment is still
ReactantServerNode, one worker subprocess per GPU.

Two properties are worth knowing before using it:

- `device` is the ordinal among the devices VISIBLE to the process, the same numbering CUDA uses.
Which physical card that is stays out of band (`CUDA_VISIBLE_DEVICES` or whatever the process
prefers), exactly as it is for a worker under the supervisor.
- Reactant's XLA client is process-global and is created by the first server, so `mem_fraction` and
the preallocated arena are fixed for the whole session. The extension records what the first CUDA
start committed to and refuses a later start that disagrees rather than letting it silently
inherit the existing arena.

`rserver_start` returns before the server is up (bundle loading and compilation run on a background
task, and a Kaimon tool call has a hard deadline), so the agent polls `rserver_status`. Argument
and configuration errors are raised by the call itself.

To drive the tools from a REPL rather than an agent, or after a manual `KaimonGate.stop()`:

```julia
Base.get_extension(ReactantServer, :KaimonGateExt).reinstall_kaimon_tools()
```

## Documentation

The docs are built with Documenter on its default HTML theme, with two plugins:
Expand Down
6 changes: 3 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Workspace root for the ReactantServer monorepo. This environment is not itself a package;
# it lists the member packages under [workspace] (they share the single root Manifest) and
# declares the [sources] for gRPCServer (the s-celles-merge branch of the upstream repo) and
# declares the [sources] for gRPCServer (the main branch of the upstream repo) and
# the inter-package ReactantServerCore dependency, so every member resolves them consistently.

# packages/ReactantServerExport is intentionally NOT listed here: it is the offline export
Expand All @@ -26,9 +26,9 @@ gRPCServer = "608c6337-0d7d-447f-bb69-0f5674ee3959"

[sources]
ReactantServerCore = {path = "packages/ReactantServerCore"}
gRPCServer = {url = "https://github.com/csvance/gRPCServer.jl", rev = "s-celles-merge"}
gRPCServer = {url = "https://github.com/csvance/gRPCServer.jl", rev = "main"}

[compat]
gRPCClient = "1.1.0"
gRPCServer = "0.3"
gRPCServer = "1.0.0"
julia = "1.12"
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ pulls in the heavy Reactant/XLA stack:
Offline model export lives in `packages/ReactantServerExport` (a Reactant tracing frontend plus a
PythonCall-triggered PyTorch extension); it is deliberately **not** a workspace member, so its
Lux/PythonCall weakdeps stay out of the server images. `gRPCServer` is sourced from the
`scelles-merge` tag of `github.com/csvance/gRPCServer.jl` through the workspace `[sources]`;
`main` branch of `github.com/csvance/gRPCServer.jl` through the workspace `[sources]`;
there are no git submodules.

## Acknowledgments
Expand Down
4 changes: 2 additions & 2 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
# them with a mismatched version.
#
# Build context is the repository root. Reactant, HTTP, Prometheus, and gRPCClient are registry
# deps; gRPCServer resolves from the `s-celles-merge` branch of github.com/csvance/gRPCServer.jl
# deps; gRPCServer resolves from the `main` branch of github.com/csvance/gRPCServer.jl
# via the workspace [sources]. NOTE: Manifest.toml is gitignored, so `COPY Manifest.toml` needs a
# locally generated Manifest in the build context (run `REACTANT_GPU=cuda REACTANT_GPU_VERSION=13.1
# julia --project=. -e 'using Pkg; Pkg.instantiate()'` first); a fresh clone has none.
Expand Down Expand Up @@ -76,7 +76,7 @@ COPY --from=cudalibs /usr/local/cuda/lib64/stubs/libcuda.so /opt/cuda-stub/libcu
WORKDIR /opt/reactantserver

# Workspace root environment and the member packages. gRPCServer resolves from its
# s-celles-merge branch on GitHub via the shared Manifest.toml; the remaining forks resolve from
# main branch on GitHub via the shared Manifest.toml; the remaining forks resolve from
# the registries. The worker is built on the workspace root; the entrypoint then runs on the
# ReactantServer member project. .dockerignore drops the package test trees (e.g. the large e2e
# weights) from the packages/ copy.
Expand Down
2 changes: 1 addition & 1 deletion docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ ReactantServerCore = {path = "../packages/ReactantServerCore"}
ReactantServerGateway = {path = "../packages/ReactantServerGateway"}
ReactantServerNode = {path = "../packages/ReactantServerNode"}
ReactantServerExport = {path = "../packages/ReactantServerExport"}
gRPCServer = {url = "https://github.com/csvance/gRPCServer.jl", rev = "scelles-merge"}
gRPCServer = {url = "https://github.com/csvance/gRPCServer.jl", rev = "main"}
# The landing-page plugin, from its git URL so the docs CI can resolve it;
# a local build can override this with a path entry (see CONTRIBUTING.md).
DocumenterLandingPage = {url = "https://github.com/csvance/DocumenterLandingPage.jl"}
2 changes: 1 addition & 1 deletion docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ through a gRPC control plane, without a restart.

ReactantServer is not yet registered in the General registry, so installation is from the
repository. The one build dependency beyond the workspace, the gRPC server, is sourced from the
`scelles-merge` tag of `github.com/csvance/gRPCServer.jl` through the workspace `[sources]`:
`main` branch of `github.com/csvance/gRPCServer.jl` through the workspace `[sources]`:

```
git clone https://github.com/EnzymeAD/ReactantServer.jl
Expand Down
2 changes: 1 addition & 1 deletion docs/src/manual/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ ReactantServer is a Julia workspace of five packages under `packages/` (`Reactan
`ReactantServer`, `ReactantServerGateway`, `ReactantServerClient`, `ReactantServerNode`), plus the
non-member `ReactantServerExport` for offline bundle export (see
[Architecture](../design/architecture.md)). It sources its gRPCServer dependency from the
`scelles-merge` tag of `github.com/csvance/gRPCServer.jl` through the workspace `[sources]`;
`main` branch of `github.com/csvance/gRPCServer.jl` through the workspace `[sources]`;
the remaining dependencies resolve from the package registries. After cloning, instantiate the
workspace:

Expand Down
2 changes: 1 addition & 1 deletion docs/src/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ to one another only through files and the gRPC wire protocol.
ready: `julia --project=packages/ReactantServerExport/test`.
2. **Server environment.** The workspace under `packages/` (`ReactantServerCore`,
`ReactantServer`, `ReactantServerNode`, `ReactantServerGateway`), with gRPCServer sourced from
its `scelles-merge` tag on GitHub through the workspace `[sources]`. After cloning,
its `main` branch on GitHub through the workspace `[sources]`. After cloning,
instantiate once:

```text
Expand Down
2 changes: 1 addition & 1 deletion examples/object_detection/server/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ gRPCServer = "608c6337-0d7d-447f-bb69-0f5674ee3959"
HTTP = {path = "../../../lib/HTTP.jl"}
ReactantServer = {path = "../../../packages/ReactantServer"}
ReactantServerCore = {path = "../../../packages/ReactantServerCore"}
gRPCServer = {url = "https://github.com/csvance/gRPCServer.jl", rev = "s-celles-merge"}
gRPCServer = {url = "https://github.com/csvance/gRPCServer.jl", rev = "main"}

[compat]
gRPCClient = "1.1.0"
Expand Down
2 changes: 1 addition & 1 deletion examples/transformers/server/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ gRPCServer = "608c6337-0d7d-447f-bb69-0f5674ee3959"
HTTP = {path = "../../../lib/HTTP.jl"}
ReactantServer = {path = "../../../packages/ReactantServer"}
ReactantServerCore = {path = "../../../packages/ReactantServerCore"}
gRPCServer = {url = "https://github.com/csvance/gRPCServer.jl", rev = "s-celles-merge"}
gRPCServer = {url = "https://github.com/csvance/gRPCServer.jl", rev = "main"}

[compat]
gRPCClient = "1.1.0"
Expand Down
24 changes: 21 additions & 3 deletions packages/ReactantServer/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,29 @@ SafeTensors = "eeda0dda-7046-4914-a807-2495fc7abb89"
YAML = "ddb6d928-2868-570f-bddf-ab3f9cf99eb6"
gRPCServer = "608c6337-0d7d-447f-bb69-0f5674ee3959"

# KaimonGate is the Kaimon MCP gate's session library, a weak dependency for the extension seam
# only: when it is loaded alongside ReactantServer, KaimonGateExt registers the `rserver_*`
# GateTools so an agent can start, inspect, and stop a worker in the session where the code is
# loaded. Nothing in `src/` references either, a user who never loads KaimonGate pays nothing, and
# Kaimon appends KaimonGate's OWN environment to JULIA_LOAD_PATH when it spawns a session, so the
# declaration does not oblige this project's manifest to carry it. It is in test extras so the
# suite can exercise the extension.
[weakdeps]
KaimonGate = "5ee84a8c-75bd-412f-a7b8-4e6463aa635f"

[extensions]
KaimonGateExt = "KaimonGate"

[compat]
BFloat16s = "0.6.1"
DLFP8Types = "0.1.0"
HTTP = "2"
InterProcessCommunication = "0.1.6"
JSON3 = "1.14.3"
# 1.3 is a floor, not a preference: it is the first release where `serve(tools = ...)` MERGES
# tools by name on a running gate. Under the older wholesale replacement, loading a second
# extension (or a notebook worker registering its own tools) silently dropped ours.
KaimonGate = "1.3"
NNlib = "0.9"
Prometheus = "1.5.1"
ProtoBuf = "1.3.0"
Expand All @@ -32,18 +49,19 @@ ReactantServerCore = "1.0.0"
SafeTensors = "1.2.1"
YAML = "0.4.16"
gRPCClient = "1.1.0"
gRPCServer = "0.3"
gRPCServer = "1.0.0"
julia = "1.12"

[extras]
KaimonGate = "5ee84a8c-75bd-412f-a7b8-4e6463aa635f"
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
Sockets = "6462fe0b-24de-5631-8697-dd941f90decc"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
gRPCClient = "aaca4a50-36af-4a1d-b878-4c443f2061ad"

[targets]
test = ["Test", "Logging", "Sockets", "gRPCClient"]
test = ["Test", "KaimonGate", "Logging", "Sockets", "gRPCClient"]

[sources]
ReactantServerCore = {path = "../ReactantServerCore"}
gRPCServer = {url = "https://github.com/csvance/gRPCServer.jl", rev = "s-celles-merge"}
gRPCServer = {url = "https://github.com/csvance/gRPCServer.jl", rev = "main"}
Loading
Loading