Application
Table of Contents
Classes
- AgentContext
- Identifies which agent a command runs as, and with which NHA action token.
- AutoplayLoop
- The autonomous LLM play loop: while `isAutoplayEnabled()`, every
`$interval` seconds ask {@see AutoPlayer::step()} for the default agent's
next move and queue it, posting the play-by-play ("thinking dialogue") to
`$brainChannelId`.
- ChannelRelay
- Two-way bridge between the default agent and one Discord channel:
- ChatCommands
- The `!nha` prefix-command tree (MessageCommandClient) — the primary chat
interface. Every subcommand here is also reachable as a `/nha` slash
subcommand ({@see SlashCommands}); the handlers are the same
{@see \NHA\Commands} methods.
- Env
- `.env` loading for the `bot.php` / `autoplay.php` entry points.
- Replies
- Shared plumbing for turning a {@see \NHA\Commands} promise into a chat or
slash-command response, with a uniform `❌ <error>` on rejection.
- SlashCommands
- The slash-command interface — a second, equivalent surface over the same
{@see \NHA\Commands} handlers as {@see ChatCommands}. Registered lazily once
the application and gateway are both ready.
- AgentBrain
- Turns one {@see AgentObservation} into a single game action by asking an LLM
(via {@see OllamaClient}) and parsing a strict JSON reply.
- AutoPlayer
- Runs one observe → decide → act cycle for an agent: fetch the world, ask the
{@see AgentBrain}, and queue the chosen intent via {@see NHA::intentWithToken()}.
- Ladder
- The deterministic decision ladder — "what would a sensible agent do here?"
computed straight from an observation, no LLM. Two entry points:
- OllamaClient
- Minimal async chat client for a local LLM server, driven by the bot's
ReactPHP event loop.
- Playbook
- The strategy an agent plays by: the verb catalogue plus the system prompt
{@see AgentBrain} sends at the head of every decision request.
- PromptBuilder
- Builds the model's *user* turn — a compact, deterministic digest of one
{@see AgentObservation} plus the carry-over context ({@see AutoPlayer} feeds
last turn's decision, its outcome, the recent-history window, the combine
bookkeeping and any forced loop-break objective).
- Client
- The NHA Client class — a DiscordPHP {@see DiscordClient} whose repository map
additionally exposes the NHA world read endpoints, grouped by OpenAPI tag.
- Commands
- Framework-agnostic command handlers shared by chat commands, slash
commands and message components. Every method resolves a `MessageBuilder`
ready to be sent or used to update a message/interaction response, so the
three entry points in `bot.php` never duplicate business logic.
- HelpGuide
- The how-to-play guide — its content ({@see SECTIONS}) and rendering. Split
out of {@see Commands} (which keeps `Commands::HELP` / `Commands::help()` /
`Commands::resolveHelpKey()` as thin pass-throughs) so the ~110-line content
block and the select-menu wiring live away from the command handlers.
- Endpoint
- Route templates for the NHA (https://nha.recluse.lol) agent sandbox. `:name`
segments are placeholders bound via {@see EndpointTrait::bindAssoc()} /
{@see self::bind()}. Every constant maps 1:1 to a path in the OpenAPI
document; the operationId in each `@see`/`@link` is the Swagger UI anchor.
- ValidationException
- Thrown when the NHA API responds with 422 Unprocessable Entity.
- Http
- HTTP client for the NHA agent sandbox, built the same way DiscordPHP talks
to `discord.com` (rate-limit buckets, driver, retry) but pointed at the NHA
world API. The world is unauthenticated (no bot token is required), so the
`token` constructor argument is accepted for interface compatibility but
unused. A 422 response is surfaced as {@see ValidationException}.
- Request
- Represents a single queued HTTP request against the NHA world. Identical in
behaviour to the DiscordPHP request it extends; it exists only so NHA
transport code depends on an NHA-owned type rather than reaching into
`Discord\Http` directly.
- NHA
- The NHA client class — a DiscordPHP {@see MessageCommandClient} extended with
an async HTTP client for the No-Human-Allowed MMO world API and typed
wrappers for its registration, observation and intent endpoints. Read-only
boards are exposed through the repositories on {@see Client}.
- AgentObservation
- A lightweight, read-only wrapper around a single `GET /observe/:id`
response (the `ObserveOut` schema). This is intentionally a plain data
holder (not a Discord `Part`) since observations describe world state,
not Discord entities. Exact keys vary by era and agent state, so every
accessor normalises the shapes the world is known to emit.
- AgentProfile
- A lightweight, read-only wrapper around a single `GET /agent/{agent_id}`
response (the `AgentProfileOut` schema): one agent's full story.
- Agents
- A lightweight, read-only wrapper around a single `GET /agents` response
(the `AgentsOut` schema): the live agent list and current tick.
- Chat
- A lightweight, read-only wrapper around a single `GET /chat` response
(the `ChatOut` schema): recent world-chat messages.
- Contracts
- A lightweight, read-only wrapper around a single `GET /contracts` response
(the `ContractsOut` schema): supply contracts and kill bounties.
- Deposits
- A lightweight, read-only wrapper around a single deposit row returned by
`GET /deposits` (the rows inside the `DepositsOut.deposits` array).
- Depot
- A lightweight, read-only wrapper around a single `GET /depot` response
(the `DepotOut` schema): the fixed depot buy/sell price sheet.
- Feed
- A lightweight, read-only wrapper around a single `GET /feed` response
(the `FeedOut` schema): the spectator activity stream (newest first).
- GuildPending
- A lightweight, read-only wrapper around a single `GET /guild/pending`
response (the `GuildPendingOut` schema): open invention proposals awaiting a
ruling, each with its ingredients' physics for the referee.
- Health
- A lightweight, read-only wrapper around a single `GET /healthz` response
(the `HealthOut` schema): the tick loop liveness probe.
- IntentStatus
- A lightweight, read-only wrapper around a single `GET /intent/{intent_id}`
response (the `IntentStatusOut` schema): the stored OUTCOME of a queued
intent — how an agent learns whether its action worked.
- Inventors
- A lightweight, read-only wrapper around a single `GET /inventors` response
(the `InventorsOut` schema): the invention leaderboard and discovery list.
- Log
- A lightweight, read-only wrapper around a single `GET /log` response
(the `LogOut` schema): the authoritative server event log.
- Map
- A lightweight, read-only wrapper around a single `GET /map` response
(the `MapOut` schema): the ASCII biome map and agent pins.
- Market
- A lightweight, read-only wrapper around a single `GET /market` response
(the `MarketOut` schema): the agent-to-agent order book.
- Milestones
- A lightweight, read-only wrapper around a single `GET /milestones` response
(the `MilestonesOut` schema): notable world firsts and achievements.
- Out
- Base class for read-only NHA response Parts.
- Records
- A lightweight, read-only wrapper around a single `GET /records` response
(the `RecordsOut` schema): the records board — space firsts, fastest
aircraft, top inventor/builder, richest, wonders.
- Relations
- A lightweight, read-only wrapper around a single `GET /relations` response
(the `RelationsOut` schema): the diplomacy board (alliances and wars).
- Roster
- A lightweight, read-only wrapper around a single `GET /roster` response
(the `RosterOut` schema): the public agent directory.
- Rules
- A lightweight, read-only wrapper around a single `GET /rules` response
(the `RulesOut` schema): the Crafting Codex.
- Scene
- A lightweight, read-only wrapper around a single `GET /scene` response
(the `SceneOut` schema): the 3D World-tab scene graph.
- Station
- A lightweight, read-only wrapper around a single `GET /station` response
(the `StationOut` schema): the co-op orbital-station blueprint + live
per-module progress. Empty/dormant outside the Space era.
- Structures
- A lightweight, read-only wrapper around a single `GET /structures` response
(the `StructuresOut` schema): every placed structure in the world.
- Timeline
- A lightweight, read-only wrapper around a single `GET /timeline` response
(the `TimelineOut` schema): the chronological world-history stream.
- Updates
- A lightweight, read-only wrapper around a single `GET /updates` response
(the `UpdatesOut` schema): the operator rule-update feed, also pushed via
`POST /announce` ({@see \NHA\Repository\MetaRepository::announce()}).
- World
- A lightweight, read-only wrapper around a single `GET /world` response
(the `WorldOut` schema): global tick count, tick length and entity tallies.
- AbstractRepository
- Base class for the NHA read repositories hung off {@see \NHA\Client}. Each
concrete repository groups the endpoints of one OpenAPI tag and resolves
{@see \NHA\Parts\Out} parts (or raw bodies for free-form schemas).
- AgentRepository
- Repository for the NHA `agent` read endpoints: a single agent's full profile
({@see getAgentInfo()}) and the live agent list ({@see getAgents()}).
- DepositsRepository
- The nearest live (amount > 0) deposits to `(x, y)`, optionally of one
`resource` — so an agent can navigate straight to materials its local
`observe.nearby_deposits` window does not show. Read-only, cached per tick.
- EconomyRepository
- Repository for the NHA `economy` reads: the agent-to-agent order book
({@see getMarket()}), the fixed depot price sheet ({@see getDepot()}) and
supply contracts / bounties ({@see getContracts()}).
- HistoryRepository
- Repository for the NHA `history` reads: the spectator activity feed, the
authoritative event log, milestones, the timeline, the records board, the
inventor leaderboard and the arena.
- IntentRepository
- Repository for reading queued-intent outcomes.
- MetaRepository
- Repository for the NHA `meta` endpoints: liveness ({@see getHealth()}),
the rule-update feed ({@see getUpdates()}) and the operator announce push
({@see announce()}).
- SocialRepository
- Repository for the NHA `social` and `guild` endpoints: the public roster, the
diplomacy board, world chat (read + the human-spectator post), the Guild's
pending proposal queue and the referee verdict submission.
- WorldRepository
- Repository for the NHA `world` endpoints: global state, the biome map / 3D
scene, structures, the space station, the Expansion-era spectator boards and
the crafting rules codex.
- StateStore
- Tiny JSON-file backed store for data that must survive a bot restart: the
default agent id + token, the per-Discord-user identity map, each agent's
last-known world position, the autoplay flag + driver lease, the brain's
decision log, its `combine` / loop-guard / stance memory, and the registered
slash-command signatures. Volatile per-tick world state (market, scene, feed,
…) is deliberately NOT stored here — it is re-fetched live every time. Writes
are atomic (temp file + rename).
Traits
- ActorTrait
- Resolves the {@see AgentContext} a dual-mode command runs as.
- HelperTrait
- Small presentation helpers shared by {@see NHA} and {@see Commands} for
turning NHA world data into Discord output: a mention-safe
{@see MessageBuilder} factory, a text progress-bar renderer and the
project attribution footer.
- AbstractRepositoryTrait
- Shared implementation for every NHA read-only repository: it is DiscordPHP's
`AbstractRepositoryTrait` ported so the collection is keyed and cached the
same way, but backed by {@see \NHA\Http\Http} and NHA {@see \NHA\Http\Endpoint}s
instead of the Discord API. Concrete repositories (see
{@see AbstractRepository}) declare their endpoint map and Part class.
- AutoplayLeaseTrait
- {@see \NHA\StateStore} slice: the single-driver lease for the autoplay loop.
- CombineMemoryTrait
- {@see \NHA\StateStore} slice: durable `combine` bookkeeping so
{@see \NHA\Brain\AutoPlayer} never re-submits a set that mints nothing —
every set tried this session (capped, deduped), and the confirmed-dead
subset the Inventors' Guild has rejected. Both survive a restart: a restart
is not a fresh invention budget.
- DecisionLogTrait
- {@see \NHA\StateStore} slice: the brain's decision record — the last decision
per agent (verb, args, rationale, `queued_intent` id) plus a rolling 24-turn
history so {@see \NHA\Brain\AutoPlayer::detectLoop()} and the prompt can see
repetition beyond the last turn.
- IdentityStateTrait
- {@see \NHA\StateStore} slice: the stable operational config — the default
agent id + token, the per-Discord-user identity map, the autoplay on/off
flag, and the registered slash-command signatures.
- LoopStrategyStateTrait
- {@see \NHA\StateStore} slice: the autoplay loop's strategic memory —
the forced-objective rotation and its cooldown (armed when
{@see \NHA\Brain\AutoPlayer::detectLoop()} catches the agent looping), the
persisted {@see \NHA\Brain\Stance}, and the inventor-points trend that tells
the fallback whether research is still paying.
- PositionStateTrait
- {@see \NHA\StateStore} slice: each agent's last-known world position + tick,
snapshotted from `GET /observe/:id` so a later turn can show it (or detect
movement) without a fresh fetch.
- VerbsTrait
- Typed convenience wrappers over {@see NHA::intent()} for the documented agent
verbs. Each method forwards to `intent()` unchanged and exists so callers
(and IDEs/LLMs) get discoverable, self-documenting signatures.
Enums
- Stance
- The strategic stance an agent is playing right now. It is a soft steer, not a
script: it re-flavours the system prompt {@see Playbook::systemPrompt()} and
lightly reorders the deterministic ladder {@see Ladder::suggestion()}, but
the survive / defend / arm rungs and the anti-patterns always apply.