angel.manohargupta.com (standalone position-tracker) is the single owner of
live positions UI; the replicated page here drifted against the same Angel
One data. Page now auto-redirects with a fallback link.
- /api/chat/telegram-thread proxy (token stays server-side)
- TelegramThreadCard rewrite: scrollable full history, 'Load older'
cursor pagination, 15s polling with referential-equality short-circuit,
scroll-anchored prepends, auto-stick to bottom only when already there
- New /api/positions route proxies to angel.manohargupta.com (positions + pnl-history)
- Positions page: 4 stat cards (total/unrealised/realised/open count), open table, closed-today table
- Auto-refreshes every 30s; manual refresh triggers force-poll on tracker
- Add Positions nav item to app-sidebar
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Chat history now survives hard refresh, tab close, and multi-device use.
Schema:
chat_messages(id, session_id, role, content, meta, created_at)
+ index on (session_id, created_at DESC)
Bridge endpoints:
POST /tiger/chat — unchanged externally, now persists
user + agent messages alongside the
existing LLM dispatch
GET /tiger/chat/history — ?sessionId=X&limit=200 → ordered messages
DELETE /tiger/chat/history — ?sessionId=X → wipe history
Dashboard:
/api/chat/history — proxy route, bridge token stays server-side
contexts/chat-context.tsx — ChatProvider hydrates messages from the
history endpoint on mount; clearChat()
now also hits DELETE /api/chat/history
Design: single-session model for now (DEFAULT_SESSION_ID constant matches
the openclaw agent --session-id used by the dispatch call). Multi-session
support would require session UI + session-aware routing — deferred to a
later feature sprint.
Tradeoff noted: message data is duplicated between our SQLite and whatever
state OpenClaw keeps internally. Chose duplication over coupling — if
OpenClaw session semantics change, dashboard history remains intact.
- Rebrand Tarzan → Tiger in layout metadata and header
- Bridge: point WORKSPACE_SYMLINK at the docker volume path post-migration
(/var/lib/docker/volumes/tiger_tiger-workspace/_data) — the old
/root/tiger-workspace symlink was orphaned after the April standalone
migration, causing workspace endpoint to return empty.
- Bridge: read agents.defaults.model.primary for model info + expose all
configured availableModels so the dashboard card can show them.
- Dashboard: page.tsx renders currentModel/fallbackModels/availableModels.
- Chat streaming fix (client side):
* proper SSE buffering across TCP chunks (split on \n\n, keep tail in
buffer, {stream: true} decoder for multi-byte UTF-8)
* separate status vs chunk handlers — status no longer pollutes content
* fall back to data.content in done event if streamingRef is empty
* visible parse errors instead of silent catch
* plain-text rendering while streaming, ReactMarkdown only after done —
avoids per-token markdown reparse which was killing the typing feel
Root causes:
1. tiger-bridge crash-looped for 36h on EADDRINUSE because a manual
nohup restart squatted on port 3456; systemd's tsx version couldn't
bind. Killing the squatter restored the expected tsx-src workflow.
2. ChunkLoadError on /chat: npm run build ran under a live next start
prod server, creating an in-memory manifest vs on-disk build split.
Fixed by disciplined build-then-restart.
3. Dashboard chat silently dropped responses: SSE 'status' event text
was being concatenated into the agent message content.
- Bridge: Express API server with SQLite (projects, tasks, executions, outputs)
- Dashboard: Next.js app rewired from WebSocket gateway to Tiger Bridge HTTP API
- Tasks: Kanban board with drag-drop, project management with CRUD
- Dispatch: Task dispatch to sandbox with file watcher for status updates
- UI: Container health panel, workspace browser, logs viewer, output viewer
Critical fixes:
- Use execInSandbox instead of execOnHost for container operations
- Watch symlink path instead of container-internal path
- URL-encoded params for GET requests instead of body
- PUT/DELETE support added to useBridgeRequest
Sprints 1-5 complete. Ready for VPS deployment.