feat(grid-agent): add chat and IM interactions (#123)
This commit is contained in:
@@ -28,6 +28,9 @@ observable receivers.
|
||||
| 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 |
|
||||
| Per-avatar conversation memory | `ConversationStore` mutex | 4,096 sessions / 64 MiB hard, lower `conversation` limits | monotonic expiry, deterministic compaction/LRU eviction |
|
||||
| Interaction ingress / observations | `InteractionHandle` | 8,192 each hard, lower queue configuration | bounded admission; lifecycle uses nonblocking watch state |
|
||||
| Per-avatar interaction FIFO | `InteractionCoordinator` | 4,096 senders / 64 messages each hard, lower `interaction` limits | fair ready queue, one active request per avatar/channel |
|
||||
| Interaction inference / outbound | generation tasks and channel rate limiters | 64 concurrent hard; 1,023 bytes per grid part | timeout/cancellation fencing; independent public/IM pacing |
|
||||
| LLM request slots | shared `LlmClient` semaphore | 256 hard / configured concurrent requests | async acquire or cancellation |
|
||||
| Reasoning/tool session | `ToolLoop` caller | 32 turns / 256 calls hard, with lower configured limits | total timeout, cancellation, or supersession |
|
||||
| Policy tools / approvals / schedules | `PolicyGateway` mutex | 64 tools / 4,096 approval records / 1,024 scheduler grants hard | deny before opaque authorization |
|
||||
@@ -89,6 +92,11 @@ cleanup, fencing old events and late LLM/tool results. See
|
||||
or direct IM. Group channels are not representable. The LLM projection can
|
||||
retrieve only one exact key, and recovered/untrusted summaries remain user-role
|
||||
prompt data rather than system authority.
|
||||
- Public-chat and direct-IM input crosses a bounded normalization boundary.
|
||||
Authority is derived only from channel plus sender UUID; public chat can never
|
||||
acquire operator authority. Output is safety-filtered, UTF-8 split, rate
|
||||
limited, and associated with its trigger, session, generation, and delivery
|
||||
result.
|
||||
- Signals and console output belong to the binary. The reusable core relies on
|
||||
no terminal, Unix socket, Unix signal, separator, or fixed platform path.
|
||||
|
||||
@@ -123,3 +131,6 @@ The live lifecycle and generation contract is documented in
|
||||
[`grid-agent-session.md`](grid-agent-session.md).
|
||||
The conversation isolation and persistence contract is documented in
|
||||
[`grid-agent-conversation.md`](grid-agent-conversation.md).
|
||||
The public-chat/IM admission, fairness, authorization, egress, and lifecycle
|
||||
contract is documented in
|
||||
[`grid-agent-interaction.md`](grid-agent-interaction.md).
|
||||
|
||||
61
docs/grid-agent-interaction.md
Normal file
61
docs/grid-agent-interaction.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# Grid-agent chat and instant-message interaction
|
||||
|
||||
`InteractionCoordinator` is the single bounded owner for public chat and
|
||||
one-to-one instant messages. A live session generation installs exactly one
|
||||
native `AgentManager` chat subscription and one IM subscription. Their RAII
|
||||
guards are removed before logout. Connect and disconnect state travels on a
|
||||
separate watch channel, so inbound queue saturation cannot delay generation
|
||||
cancellation or reconnect fencing.
|
||||
|
||||
## Admission and routing
|
||||
|
||||
Inputs are normalized into bounded values before enqueue. Self messages,
|
||||
objects and system chat, muted residents, typing notifications, group or
|
||||
conference IMs, malformed or oversized input, repeated delivery IDs, and
|
||||
reflections of delivered output are suppressed. Public chat is admitted only
|
||||
for a configured alias or mention, a brief nearby greeting, or a short-lived
|
||||
follow-up from a resident already engaged by the agent. Ambient region chat is
|
||||
not sent to the model.
|
||||
|
||||
Public chat always has `Public` origin, even when the resident UUID appears in
|
||||
the operator allowlist. Public commands receive a fixed denial; public LSL
|
||||
requests remain policy-gated. Direct-message authority is derived solely from
|
||||
the sender UUID in `authorized_avatar_uuids`. Text claiming to be an operator
|
||||
cannot change that origin. Unprivileged IM remains informational, while an
|
||||
authorized IM may expose only the tools returned by `PolicyGateway` for its
|
||||
immutable request context. Unknown or unregistered tools fail closed.
|
||||
|
||||
Each avatar and channel has an independent FIFO with fragment debounce. A
|
||||
round-robin ready queue permits at most one active request per FIFO and enforces
|
||||
the configured global inference cap, so a slow resident does not block other
|
||||
residents or lifecycle work. Direct-message context expires after 24 hours as
|
||||
defined by `ConversationStore`; public and direct context never mix.
|
||||
|
||||
## Delivery and safety
|
||||
|
||||
Model work has a configured deadline and shares generation cancellation.
|
||||
Visible text is checked for credential, authorization, hidden-prompt, and tool
|
||||
schema markers; URLs are omitted and ASCII mentions are neutralized. The total
|
||||
response is bounded, then split only at UTF-8 boundaries into at most 1,023-byte
|
||||
grid messages. Public chat and IM use independent rate limiters.
|
||||
|
||||
Every outbound part carries its trigger delivery ID, conversation session ID,
|
||||
session generation, channel, part index, and part count. A delivery observation
|
||||
records success, timeout, policy denial, or failure plus the number of parts
|
||||
actually delivered. Fixed busy/failure text is emitted only for an admitted
|
||||
interaction. Successful public replies also publish a content-free attention
|
||||
request for later avatar behavior work.
|
||||
|
||||
## Shutdown and focused verification
|
||||
|
||||
Disconnect cancels all generation tasks and drops queued input. Reconnect
|
||||
starts a fresh generation without clearing the bounded duplicate/reflection
|
||||
history. Shutdown disconnects first, joins every model/delivery task within the
|
||||
configured deadline, and flushes conversation persistence. No callback or task
|
||||
is detached.
|
||||
|
||||
```sh
|
||||
cargo test --locked -p metacrate-grid-agent --lib interaction_tests
|
||||
cargo test --locked -p metacrate-grid-agent --test dependency_policy
|
||||
cargo clippy --locked -p metacrate-grid-agent --all-targets -- -D warnings
|
||||
```
|
||||
Reference in New Issue
Block a user