Files
timmy-tower/the-matrix
Replit Agent 494393017c task-28 fix3: complexity contract, consistent token headers, npub-only prompt
1. edge-worker.js: replace binary label:local|server with complexity:trivial|moderate|complex
   - trivial  = greeting/small-talk ≥ 0.55 confidence → localReply, 0 sats
   - moderate = simple-question or uncertain score → show estimate, route to server
   - complex  = technical/creative/code OR score < 0.40 → show estimate, route to server
   - model-unavailable fallback → moderate (safe default, not 'server')

2. edge-worker-client.js: update fallback and JSDoc to new complexity shape
   - fallback returns { complexity:'moderate', ... } instead of { label:'server', ... }

3. ui.js: triage driven by cls.complexity, not cls.label
   - trivial + localReply → local answer, 0 sats badge, no server call
   - moderate/complex → _fetchEstimate() fired on classify outcome (not just debounce)
     then routed to server via WebSocket

4. session.js: X-Nostr-Token attached consistently on ALL outbound session calls
   - _startDepositPolling: GET /sessions/:id now includes X-Nostr-Token header
   - _startTopupPolling: GET /sessions/:id now includes X-Nostr-Token header
   - _tryRestore: GET /sessions/:id now includes X-Nostr-Token header
   - _createTopup: POST /sessions/:id/topup now includes X-Nostr-Token header

5. nostr-identity.js: _canSign flag tracks signing capability separately from pubkey
   - initNostrIdentity sets _canSign=true only when NIP-07 or privkey is available
   - npub-only discovery sets _pubkey but _canSign=false → prompt IS scheduled
   - Prompt shown when !_pubkey || !_canSign (not just !_pubkey)
   - Prompt click handlers set _canSign=true after connecting NIP-07 or generating key
   - refreshToken only called when _pubkey && _canSign (avoids silent failures)
2026-03-19 19:02:45 +00:00
..

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)

Stack

  • Three.js 0.171.0 — 3D rendering
  • Vite 5 — build + dev server
  • crypto.randomUUID() — secure client session IDs (no external library)