- Backend: print STAR_BACKEND_PORT hint so users can change port without
editing app.py (e.g. when 18791 is already in use).
- office-agent-push.py: print state file source and LOCAL_STATUS_URL at
startup so users can verify path and URL when state does not update.
Made-with: Cursor
- POST /assets/generate-rpg-background now returns immediately with a
task_id, runs generation in a background thread
- Added GET /assets/generate-rpg-background/poll?task_id=xxx for
frontend to poll completion status
- Frontend polls every 3s with elapsed time display
- Prevents Cloudflare's 100s timeout from killing the connection
- Also extracted shared error handling into _handleGenError()
- add_no_cache_headers now only applies long-cache headers to 2xx responses
- non-2xx static responses (e.g. 404) get no-cache to prevent CDN from
caching error pages (which was the root cause of office.hyacinth.im
failing to load - Cloudflare cached a 404 for phaser.js for 2.7 days)
- add version cache-bust param to phaser.js script tag (matching all
other static assets)
Avoid hardcoded 127.0.0.1:18791 by reading STAR_BACKEND_HOST/STAR_BACKEND_PORT in Electron and backend startup, so different local setups can run without code changes.
Made-with: Cursor
Rebuild the Electron standalone interface with synchronized i18n/state behavior, improved mini-window sprite rendering, and DOM-based office plaque editing for better readability and customization.
Made-with: Cursor
Previously every poll (3.5s per client) unconditionally wrote both
agents-state.json and join-keys.json. Now tracks a dirty flag and
only persists when cleanup actually modifies state (expired agents
removed or agents marked offline).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend: add html.escape() to clean_text() so user-controlled input
(agent names, details) is entity-escaped before storage.
Frontend: memo content now uses textContent instead of innerHTML
(newlines handled by CSS white-space:pre-wrap). Guest agent names
are escaped before interpolation into template literals to prevent
stored XSS via malicious agent names in onclick handlers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Each /yesterday-memo request used random.choice for the wisdom quote,
causing the card to flicker on frontend polling. Now uses date-based
index (YYYYMMDD % len) so the same quote shows consistently all day.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Previously /set_state only wrote to state.json, but /agents reads
from agents-state.json. The main agent's status in agents-state.json
was stale. Now save_state() also updates the isMain=true entry in
agents-state.json to keep both files consistent.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The backend runs on port 19000 (to avoid conflict with OpenClaw on
18791), but docs and scripts referenced 18791. Unified all references
to 19000 and made the port configurable via OFFICE_PORT env var.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add clean_text(), HMAC token auth for set_state, same-origin check,
structured logging with trace IDs, and agent state normalization.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>