88 lines
4.9 KiB
Markdown
88 lines
4.9 KiB
Markdown
# Grid-agent architecture foundation
|
|
|
|
The grid agent is a workspace-owned Rust library and small service binary. Its
|
|
core depends on Tokio for scheduling and bounded channels. Its `live-grid`
|
|
feature owns the existing `libremetaverse` composition root for grid protocol
|
|
managers; the default offline graph does not compile live transports. It does
|
|
not create a second login, UDP, capabilities, inventory, or world client. It contains no
|
|
CLR/.NET loading, sidecar, subprocess adapter, provider SDK, native ABI, or
|
|
platform-specific core path.
|
|
|
|
## Ownership and bounds
|
|
|
|
`AgentService::start` is the sole task-creation point. It validates the complete
|
|
configuration before allocating channels, calling a backend, or permitting
|
|
network access. `ServiceHandle` then exclusively owns cancellation, both join
|
|
handles, the control sender, and observable receiver.
|
|
|
|
| Resource | Owner | Hard/configured bound | Backpressure/termination |
|
|
| --- | --- | --- | --- |
|
|
| Grid-event queue | coordinator receives; backend sends | 8,192 / `grid_event_queue` | async send or cancellation |
|
|
| Control queue | coordinator receives; handle sends | 256 / `control_queue` | async send; closed after stop |
|
|
| Observable queue | handle receives; coordinator/backend send | 8,192 / `observable_queue` | async send or cancellation |
|
|
| Backend task | `ServiceHandle.tasks[0]` | exactly one | shared cancellation token, joined first |
|
|
| Coordinator task | `ServiceHandle.tasks[1]` | exactly one | shared cancellation token, joined second |
|
|
| Body / message | typed boundary owners | 8 MiB / 64 KiB hard ceilings, with lower configured limits | rejected before enqueue |
|
|
| Conversation / tool calls | request owner | 256 messages / 64 calls, with lower configured limits | rejected before request |
|
|
| Authorized avatars | immutable `AgentConfig` set | 1,024 hard ceiling, lower configured limit | malformed, nil, duplicate, and wildcard input rejected |
|
|
| Configuration / secret file | loader | 64 KiB / 16 KiB | regular non-symlink file only |
|
|
|
|
`BoundedText` and `BoundedVec` make message and collection ceilings part of the
|
|
type. Dynamic configuration can lower these absolute ceilings but cannot raise
|
|
them. Backend error text is not forwarded; observations publish a fixed bounded
|
|
diagnostic.
|
|
|
|
## State machine and shutdown
|
|
|
|
The explicit service states are `starting -> running <-> paused -> stopping ->
|
|
stopped`, with `failed` reserved for task failure. The offline backend publishes
|
|
`BackendReady`, after which the coordinator enters `running`. A shutdown control,
|
|
direct handle shutdown, backend failure, closed owner queue, or handle drop
|
|
triggers the same cancellation token.
|
|
|
|
Orderly shutdown first cancels, joins the backend, and then joins the
|
|
coordinator. Each join has the validated shutdown timeout. A late task is
|
|
aborted and awaited before return. A partially polled shutdown future only
|
|
borrows each join handle, so cancelling that future leaves every task in the
|
|
handle's fixed ownership slots for a retry or final drop. Dropping the handle
|
|
cancels and aborts all remaining owned tasks, so no task is detached. A
|
|
feature-enabled live adapter drops its
|
|
`LibremetaverseClientOwner` last, invoking the existing client ownership
|
|
shutdown.
|
|
|
|
## Trust boundaries
|
|
|
|
- JSON configuration and environment text are untrusted. Unknown fields,
|
|
oversized files, invalid booleans, conflicting modes, non-HTTP(S) URLs,
|
|
URL fragments, malformed/noncanonical/nil UUIDs, wildcard authorization,
|
|
multiline secrets, and unsafe limits fail before startup.
|
|
- `SecretString` and `EndpointUrl` are the only credential-bearing value types.
|
|
Secrets are never serializable or printable. Endpoint diagnostics replace
|
|
user information, passwords, and the complete query.
|
|
- Grid input crosses `GridBackend` only through bounded `GridEvent` values.
|
|
The `live-grid` feature supplies `LibremetaverseClientOwner`; live
|
|
implementations must own it and reuse its client and managers.
|
|
- World changes cross only `WorldMutator::apply`, which always receives the
|
|
proposed call and an explicit `PolicyDecision`. This issue supplies no live
|
|
mutation implementation.
|
|
- Signals and console output belong to the binary. The reusable core relies on
|
|
no terminal, Unix socket, Unix signal, separator, or fixed platform path.
|
|
|
|
## Dependency diagram
|
|
|
|
```text
|
|
metacrate-grid-agent binary (portable Ctrl-C + config path)
|
|
|
|
|
v
|
|
AgentService -> bounded Tokio channels/tasks -> injected GridBackend
|
|
| |
|
|
v v
|
|
typed config/events/policy boundaries live-grid feature boundary
|
|
| |
|
|
+-----------------> libremetaverse-types +--> libremetaverse::GridClient
|
|
```
|
|
|
|
The package has no build script or direct native dependency. The focused
|
|
`dependency_policy` test rejects subprocess launch sites, unsafe/native ABI
|
|
source, build scripts, and unreviewed direct dependency names in this package.
|