No description
  • Java 88.5%
  • Lua 5.9%
  • JavaScript 2.6%
  • Python 2.6%
  • HTML 0.3%
  • Other 0.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Stella Reine 029b2df27a feat: rack provisioning, EEPROM writer and web link
Adds the fleet-provisioning half of AgentOS:

- Rack Provisioner block: template GUI laid out like OpenComputers' own
  server screen, builds every server across every rack on its component
  network to one profile, and can start, stop, refresh or eject boot ROMs
  fleet-wide. Builds as many whole servers as the parts allow rather than
  refusing the lot, and never leaves one half-fitted.
- EEPROM Writer block: burns the PXE boot ROM into blanks on its own tick,
  with an item handler shaped so any cable or conduit can feed it.
- Config Card: copies a rack's bus wiring between racks, and in fill mode
  stocks a rack with servers from the player's inventory.
- Web link: the web service now owns .secret-token and the mod dials out to
  it, so a dashboard can live off-box.
- Node roles are reassignable after enrollment, over OC, the bridge and the
  terminal; hardware reporting now probes the machine instead of guessing.
- Generated block textures and a creative tab; item models are registered,
  which they never were.

83 tests pass. The in-game behaviour of the provisioning blocks is only
partly verified; see AGENTS.md.
2026-08-13 10:58:22 -05:00
.github/workflows init 2026-08-12 14:25:54 -07:00
docs/superpowers init 2026-08-12 14:25:54 -07:00
gradle init 2026-08-12 14:25:54 -07:00
src feat: rack provisioning, EEPROM writer and web link 2026-08-13 10:58:22 -05:00
tools feat: rack provisioning, EEPROM writer and web link 2026-08-13 10:58:22 -05:00
web-service feat: rack provisioning, EEPROM writer and web link 2026-08-13 10:58:22 -05:00
.gitignore init 2026-08-12 14:25:54 -07:00
AGENTS.md feat: rack provisioning, EEPROM writer and web link 2026-08-13 10:58:22 -05:00
build.gradle init 2026-08-12 14:25:54 -07:00
CHANGELOG.md init 2026-08-12 14:25:54 -07:00
gradle.properties init 2026-08-12 14:25:54 -07:00
gradlew init 2026-08-12 14:25:54 -07:00
gradlew.bat init 2026-08-12 14:25:54 -07:00
LICENSE init 2026-08-12 14:25:54 -07:00
README.md feat: rack provisioning, EEPROM writer and web link 2026-08-13 10:58:22 -05:00
settings.gradle init 2026-08-12 14:25:54 -07:00
tags.properties init 2026-08-12 14:25:54 -07:00

AgentOS

AgentOS turns real OpenComputers machines and server racks into authenticated distributed networks. Online nodes contribute compute and agent slots to jobs, radar, security, and timed virtual attacks. The Minecraft server owns all authoritative state; the browser dashboard is a separate, low-memory Java service.

Platform

  • Minecraft 1.12.2 + Forge/Cleanroom
  • Java 25 only
  • OpenComputers 1.7.5.192 required
  • No Dynmap or HBM dependency. The world map uses a Dynmap-style bounded tile queue and radar exposes a detection-provider extension point for future HBM support.

Build

$env:GRADLE_USER_HOME='.gradle-tmp'
.\gradlew.bat clean test build :web-service:installDist --no-daemon

Outputs are under build/libs and web-service/build/install/web-service. This repository is configured for local development; do not run publishing tasks unless intentionally releasing it.

Install and play

  1. Put the AgentOS mod and OpenComputers in the Cleanroom server mods folder.
  2. Start the server. AgentOS creates config/agentos-bridge.properties with a private secret and loopback port.
  3. Craft the Agent Network Controller and Radar Controller using their generated recipes.
  4. Obtain/craft the registered AgentOS installation floppy, insert it into an OC computer, and boot/run /install.lua.
  5. Install to a writable hard drive, remove the floppy, then boot the drive.
  6. Run /bin/agentos.lua. Create a network or join one using its UUID and password. The first creator also bootstraps a web administrator.
  7. Keep machines connected to an agentos_gateway. Their daemon reconnects, heartbeats every ten seconds, and records agentos_* signals.
  8. Connect a Radar Controller to the same OC network and call component.agentos_radar.linkNetwork(networkId). Terrain is mapped independently; the radar's range applies to contacts and its location/range are visible only to users signed into that Agent Network.

Node credentials are stored on each installed OC disk. Revoking one node does not rotate other credentials. Nodes become offline after 30 seconds without a valid heartbeat and are always revalidated after server restart.

Rack Provisioner

Deploying racks by hand means pulling every server out, opening it, inserting a flashed EEPROM and putting it back. The AgentOS Rack Provisioner block does that in one call, and never needs the machines to boot: OpenComputers keeps EEPROM contents and a server's installed components in plain item NBT, so the block writes them directly.

Place it touching the inventories you want it to work with (a server rack, a chest of blank EEPROMs, …) and drive it from any OC computer through the agentos_provisioner component. Sides are the usual 0-5 facings.

local p = component.agentos_provisioner
p.setController(component.modem.address)   -- the machine running provision.lua
p.list(3)                                  -- what is on that side
p.transfer(3, 2, 4)                        -- transposer: move 4 items side 3 → 2
p.flash(3, 1)                              -- stamp the PXE ROM onto one EEPROM
p.provisionRack(2, 3)                      -- every server in the rack on side 2,
                                           -- taking blank EEPROMs from side 3

provisionRack returns how many servers it provisioned and emits an agentos_provision signal. Re-running it is safe: a server that already has a boot ROM has that ROM rewritten rather than being skipped or consuming another EEPROM. The stamped ROM is the same pxe-bios.lua the scripts/ PXE stack uses — it is bundled in the mod — with the controller address baked into its data area, so a provisioned rack netboots and images itself as soon as provision.lua is running. Follow up with agentos-fleet enroll all to join them to a network.

External dashboard

The web service stays outside the Minecraft JVM. Copy web-service/agentos-web.env.example and launch the installed distribution with those environment variables. Default addresses:

  • private mod bridge: 127.0.0.1:8787
  • web dashboard: 127.0.0.1:8790
  • radar tiles: <world>/agentos/radar

For remote users, place a normal TLS reverse proxy in front of port 8790. Never expose port 8787 or its shared secret.

Linking the mod to the web (.secret-token)

The web service owns the link secret. On first start it writes $AGENTOS_WEB_DATA/.secret-token (owner-readable only) and prints it once.

  1. Start the web service and copy the printed token.
  2. On the Minecraft server, edit config/agentos-web-link.properties:
    url=https://agentos.example.net
    token=<the .secret-token value>
    intervalSeconds=2
    
  3. Restart the server. The mod dials out and pushes a snapshot of every network to POST /api/link/state, authenticating with Authorization: Bearer <token>. The log shows AgentOS web link pushing to ….

Because the mod initiates the connection, the dashboard can live on a host that cannot reach the game server at all. Rotate the token with bin/web-service --rotate-token, then update each linked server.

Limitation: sign-in and every control action still go through the loopback bridge, so a dashboard that cannot reach AGENTOS_BRIDGE_URL runs in read-only link-only mode (/api/state answers from the pushed cache and reports X-AgentOS-Source: link). A remote dashboard therefore needs either co-location with the server, a tunnel to port 8787, or the command channel that is not built yet. The service uses HttpOnly/SameSite cookies, owner-only persistent sessions keyed by cookie hash, CSRF tokens, signed mod-issued user tickets, per-user named layouts, and server-side permission checks.

Dashboard roles are Administrator, Operator, Security, and Viewer. Every mutation is reauthorized by the mod. Viewer requests cannot write even if endpoints are called manually.

Lua API and signals

require("agentos") exposes create, join, reconnect, status, allocation, jobs, alerts, and virtual attack operations. The gateway also exposes these directly as OpenComputers callbacks. Important signals include:

  • agentos_node, agentos_auth, agentos_alert
  • agentos_job, agentos_radar, agentos_security, agentos_attack

Use /bin/agentos-diag.lua for local disk/gateway/authentication checks. The daemon logs received signals to /var/log/agentos.log.

Operations and recovery

  • Back up the world normally; network accounts, credential hashes, node registrations, allocations, and retained events live in world saved data.
  • Dashboard layouts live under AGENTOS_WEB_DATA/layouts and radar PNGs live under the world radar directory.
  • Browser sessions live under AGENTOS_WEB_DATA/sessions as owner-only files keyed by cookie hash and expire after 12 hours.
  • If the web service fails, Minecraft and AgentOS continue. Restart the external service without restarting the game.
  • If the bridge secret leaks, stop the web service, delete config/agentos-bridge.properties, restart Minecraft to generate a new secret, then update the web environment.
  • Repair an OC installation by booting the floppy and choosing Repair/reinstall; its existing network credential file is preserved.
  • The whole already-generated world is discovered from Anvil region headers and pre-rendered incrementally. Existing chunks are loaded at a bounded rate, captured on the server thread, handed to a two-worker PNG queue, and queued for unload again. This never generates new terrain.
  • Radar scans remain bounded to loaded chunks. A network snapshot contains only that network's active radar coordinates and effective ranges, so another network's hardware is never exposed on its map.

Development

Core logic has JUnit tests independent of Minecraft. runServer is the Cleanroom dev-server smoke task. The private bridge health endpoint is /api/v1/health; browser traffic must use the external service instead.