Computer's model call, session continuity, and answers ran in the Vercel
deployment, reached by a signed forward from a host bridge. That put the model
credential in the deployment (one revoked provider key took the Discord surface
down) and kept replies depending on a Vercel function.
The channel is now the runtime: channels/discord/index.ts holds the Gateway
socket, admits a mention with the same tested policy modules, runs the turn on
the Computer Zo persona over /zo/ask, and posts the reply. The persona owns the
prompt and the model, so no model credential lives in the repository.
Retires the forward path it replaces: bridge/discord-gateway/,
agent/channels/discord-mentions.ts, the bridge HMAC and its header constants in
lib/discord-bridge.ts, and DISCORD_BRIDGE_SECRET. lib/host-secrets.ts now takes
the names to fill and includes ZO_CLIENT_IDENTITY_TOKEN.
The reconnect path is single by construction, which is the defect #92 filed
against the bridge it replaces: one socket per attempt, a pending-reconnect
guard, and a stale socket's close ignored.
Verified: typecheck clean, 165/165 tests pass, eve build succeeds on Node 24,
and an end-to-end harness against stub Zo, stub Discord REST, and a stub Gateway
shows one admitted mention producing one /zo/ask call carrying the persona id,
the reply posted into the originating channel, a second mention continuing the
same conversation, a non-allowlisted author and a bot message dropped, and
exactly one socket after a forced reconnect.
Computer's Discord turn ran in the Vercel deployment: a bridge on the host forwarded each admitted mention to
POST /eve/v1/discord-mentionsand the deployment ran the model call. That kept the model credential in the deployment, so one revoked provider key took the surface down, and it made every reply depend on a Vercel function.This moves the brain to the Zo host.
channels/discord/index.tsis now the whole runtime: it holds the Gateway socket, admits a mention with the same tested policy modules, runs the turn on the Computer Zo persona over/zo/ask, and posts the answer back into the originating channel or thread. The persona owns the prompt and the model, so no model credential lives in this repository or on Vercel.What is retired
bridge/discord-gateway/index.tsandagent/channels/discord-mentions.ts, the two halves of the forward path.lib/discord-bridge.ts, plusDISCORD_BRIDGE_SECRET: nothing signs or verifies a forward any more.bridge/**drops out of the deploy path filter;channels/**replaces it. The service label becomescomputer-discord, matchinggoop-discordanddata-discord.lib/host-secrets.tsnow takes the names to fill and includesZO_CLIENT_IDENTITY_TOKEN, which is the credential/zo/askis called with.The reconnect defect
Issue #92 filed a bridge that held two Gateway sessions and reconnected every minute:
scheduleReconnectcalledsocket.close(), whose own close listener calledscheduleReconnectagain. The replacement is single by construction: one socket per attempt, a pending-reconnect timer guard, and a stale socket's close ignored. A forced close in the end-to-end harness shows exactly one replacement socket.Verification
pnpm run typecheckclean;pnpm test165/165 (three fixtures updated for the retired secret and the new ready line).build:evesucceeds on Node 24, so the authored app still compiles without the deleted channel./zo/askcall carrying the persona id, the reply is posted into the originating channel, a second mention continues the same conversation, and a non-allowlisted author and a bot-authored message are dropped.Not in this PR: the web surface. Vercel still runs the eve agent for web chat and the GitHub path, so
AI_GATEWAY_API_KEYand the Blob-backed factory remain. That cut is the next one.Closes #92.