Office World Actions: chat-commanded errands in the 3D world - #864
Merged
Conversation
Contributor
Greptile SummaryThis PR adds chat-commanded errands to the Office 3D world. The main changes are:
Confidence Score: 5/5This looks safe to merge.
Important Files Changed
Reviews (3): Last reviewed commit: "Fix Greptile review findings on world ac..." | Re-trigger Greptile |
- Accept CRLF newlines in world-action fence blocks so protocol JSON from CRLF-emitting models/transports executes instead of leaking into chat (+ regression test). - Close the rep panel when a mission's interaction hold times out: the sim emits "ended" and walks the agent home, so the panel must not stay open serving an interaction whose agent already left.
fathah
force-pushed
the
office-intelligent
branch
from
July 22, 2026 04:40
ac9ed7e to
d0b5e3b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Tell an agent in the office chat "go to the bank and check my balance" — its avatar stands up, walks the sidewalk route to the bank, stops in front of the teller (or the ATM if you asked for it), the camera flies in after it, and the interaction modal opens with the balance already fetching. Closing the modal sends the agent walking home.
The agent's own LLM does the understanding — no keyword matching. This is the first step toward a fully intelligent 3D world (agentic transactions, purchases, driving, more rooms), and the pipeline is built so each future ability is a small extension, not a new system.
How it works
Four decoupled stages:
Protocol —
office3d/interactions/worldActions.tsThe chat injects a vocabulary of world abilities as a request-side system message (never persisted — transcripts stay clean). When the user's request maps to an ability, the model appends a fenced
```world-actionJSON block to its reply. The renderer strips the block from the visible text and validates it.ABILITIESlist, so prompt and parser can't drift apart. Adding "send 0.1 ETH to prompt-engineer" later = one catalog entry + a parse case + a plan case.dovalues are stripped but run nothing — bad model output degrades to a normal chat reply, never a wrong errand.Orchestration —
Office.tsxPlans the parsed actions into a mission (bank operations force the bank; teller vs ATM picks the representative), dispatches it, closes the chat, and pulls the camera back to the city so you watch the walk. On arrival: fly into the building, select the agent, open
RepInteractionPanelwith anautoActionthat runs as if clicked. Any way the modal goes away (close, Escape, exiting the interior, walk-mode movement) completes the mission and sends the agent home. Walk mode keeps its own camera — no hijacking.Mission bus —
office3d/interactions/missionBus.tsA tiny module-level pub/sub bridging the DOM UI and the r3f Canvas (React context can't cross the Canvas boundary, and the sim mutates refs without re-rendering). Plain
Sets, zero allocations in the frame path — consistent with the low-end-device efficiency contract of the rest of Office 3D.Simulation —
AgentsLayer.tsx+trips.tsMissions reuse the existing trip machinery (routes, collision, crowd separation) with a new
"visit"phase: join the route at the nearest waypoint (missions can start from any desk, the rest room, or mid-trip), walk to a named interaction stop (TripRoute.stops, keyed by rep id — reusing proven collision-clear points at the teller counter and ATM row), emitarrived, hold while the modal is open (2 min cap; 15 s for a plain "go there"), then walk home in reverse. Unlike random trips, a working agent is not turned around — being sent on an errand while working is the point. A superseding mission cleanly ends the previous one.Bug fix: door-gate routing (stuck-agent deadlock)
Commanded missions exposed a latent routing bug:
routeTargetchecked the partition crossing before the CEO-office crossing, and aimed at the far side of a door in one hop. From a CEO seat (or anywhere south of the door band) the straight line crossed a wall outside the door gap, and wall-follow deadlocks in concave pockets (wall corner + couch/plants) — the agent walked in place forever. Random trips never hit this because they only ever started from the rest room.Fixed in a new shared module
office3d/core/routing.ts: every room crossing is a two-hop door gate (near-side gate point first, then the far side), so the wall-crossing hop passes through the door gap from any start position, and the CEO office's own doorway is routed before the divider. Regular seat walks get the fix too (the CEO → rest-room walk had the same latent bug).RepInteractionPanel:
autoActionNew optional prop that runs a commanded action exactly once when the panel opens — gated on the account scope having resolved, because the accountId resolution changes the cache key, bumps
requestSeq, and would silently drop an action fired at mount.Tests
worldActions.test.ts— every advertised prompt example must itself parse (vocabulary can't teach dead syntax); parse/strip round-trip; malformed and unknown blocks degrade safely;create_accountnormalises to the teller; planning forces the bank and picks the right rep.missionBus.test.ts— pub/sub contract incl. unsubscribe (a torn-down AgentsLayer must never act on a stale mission).routing.test.ts— replays the previously-deadlocking routes hop by hop against the real wall rectangles fromlayout.tsand asserts no hop crosses a wall; verified to fail against the old logic.Full suite: 1770 passing (166 files), typecheck + lint clean,
lat checkpasses.Docs
New
lat.md/office-world-actions.md(protocol, bus, commanded trips, orchestration, test specs) plus cross-links fromoffice-interactions.mdandoffice-3d-interiors.md(door-gate routing under Collision).Extending (the recipe)
To add a future ability (transfer, purchase, drive, meeting room):
ABILITIESentry inworldActions.ts(the prompt updates itself) + aparseActioncase + aplanWorldActionscase.TripRoute(+ named stops) intrips.ts.Notes / follow-ups
systemhistory role touser(apiHistory); the instruction still works, but a first-class system-message field there would be cleaner.