## Changes ### the-matrix/js/session.js (new module) - Full session lifecycle: create → invoice → deposit poll → active → request → topup → restore - Presets + number input for deposit (200–10,000 sats) and topup amounts; reads from input on submit - Input validation: 200–10,000 sats range enforced in JS before API call - Auto-closes panel after deposit payment confirms (closePanel in _startDepositPolling success branch) - Low-balance condition fixed: `isSessionActive()` (covers both 'active' and 'paused') not just `active` - HUD: updates `#session-hud-balance` span with "Balance: X sats"; `#session-hud-topup` link clickable - Topup reads from `#session-topup-input` number field, same validation - localStorage restore: validates session via GET, restores macaroon + balance + UI state on reload - Expired/401 sessions: clears storage, resets all UI - Request in-flight guard prevents double-submit; send button disabled during request ### the-matrix/js/ui.js - `setSessionSendHandler(fn)` — override input bar submit when session active - `setInputBarSessionMode(active, placeholder)` — green border + placeholder swap - `send()` routes to session handler when set, falls back to WS visitor_message ### the-matrix/index.html - `#top-buttons` flex container: "⚡ SUBMIT JOB" (blue) + "⚡ FUND SESSION" (teal) side-by-side - `#session-hud` with `#session-hud-balance` span + `#session-hud-topup` link (pointer-events: all) - `#session-panel` (left slide-in): fund / invoice / active / topup steps - Fund + topup steps each have preset buttons AND a number input (200–10k range) - Added 10k preset button to both step grids - `#visitor-input.session-active` green pulse border animation (3s keyframe) - `#low-balance-notice` strip above input bar with inline Top Up button - CSS: `.session-amount-input` green styled, spin buttons hidden; `.session-amount-row` flex layout - CSS: `.primary-green` / `.muted` panel button variants for session panel theme ### the-matrix/js/main.js - Import + call `initSessionPanel()` in firstInit block ## Verification - npm run build: clean (0 errors, 15 modules) - Testkit: 27/27 PASS (session tests 11–16, 22 all green)
Timmy Tower World
A Three.js 3D visualization of the Timmy agent network. Agents appear as glowing icosahedra connected by lines, pulsing as they process jobs. A matrix-rain particle effect fills the background.
Quick start
npm install
npm run dev # Vite dev server with hot reload → http://localhost:5173
npm run build # Production bundle → dist/
npm run preview # Serve dist/ locally
Configuration
Set these in a .env.local file (not committed):
VITE_WS_URL=ws://localhost:8080/ws/agents
Leave VITE_WS_URL unset to run in offline/demo mode (agents animate but
receive no live updates).
Adding custom agents
Edit one file only: js/agent-defs.js
export const AGENT_DEFS = [
// existing agents …
{
id: 'zeta', // unique string — matches WebSocket message agentId
label: 'ZETA', // displayed in the 3D HUD
color: 0xff00aa, // hex integer (0xRRGGBB)
role: 'observer', // shown under the label sprite
direction: 'east', // cardinal facing direction (north/east/south/west)
x: 12, // world-space position (horizontal)
z: 0, // world-space position (depth)
},
];
Nothing else needs to change. agents.js reads positions from x/z,
and websocket.js reads colors and labels — both derive everything from
AGENT_DEFS.
Architecture
js/
├── agent-defs.js ← single source of truth: id, label, color, role, position
├── agents.js ← Three.js scene objects, animation loop
├── effects.js ← matrix rain particles, starfield
├── interaction.js ← OrbitControls (pan, zoom, rotate)
├── main.js ← entry point, rAF loop
├── ui.js ← DOM HUD overlay (FPS, agent states, chat)
└── websocket.js ← WebSocket reconnect, message dispatch
WebSocket protocol
The backend sends JSON messages on the agents channel:
type |
Fields | Effect |
|---|---|---|
agent_state |
agentId, state |
Update agent visual state |
job_started |
agentId, jobId |
Increment job counter, pulse |
job_completed |
agentId, jobId |
Decrement job counter |
chat |
agentId, text |
Append to chat panel |
Agent states: idle (dim pulse) · active (bright pulse + fast ring spin)