- Create OfficePanel with Office floor plan and Org Chart view modes
- Desk-style cards with status glow, emoji indicators, pulse animation for busy agents
- Agent detail modal with task stats, activity, session info
- Auto-refresh every 10 seconds for real-time updates
- Status summary in header (working/idle/error/away counts)
- Add OfficeIcon and office nav item in CORE group
- Register office route in page.tsx
Closes#115
Co-authored-by: bhavikprit <petrobhakti@gmail.com>
* feat: add workspace-scoped auth sessions and core API filtering
* feat: extend workspace scoping to search status standup and messaging
* feat: scope agent connect github and alert workflows by workspace
* fix: scope status sync and session alerts by workspace
* feat: add phase2 workspace migration and scope chat pipeline alerts
* feat: add model selection for agents and cron jobs
* feat: add deterministic agent avatars to task and squad views
* feat: add read-only cron calendar and agenda views
* feat: render task descriptions with markdown
Workspace file is now the primary source for soul.md with DB as
fallback. Reads prefer workspace → DB. Writes go to both. Config sync
imports soul.md from each agent's workspace using double resolveWithin
guard to prevent path traversal.
* fix: migrate middleware.ts to proxy.ts for Next.js 16 (#88)
Next.js 16 deprecated the `middleware` file convention in favor of
`proxy`. The proxy runs on the Node.js runtime instead of Edge, so
safeCompare now uses crypto.timingSafeEqual instead of manual XOR.
All auth logic, CSRF validation, host matching, and security headers
are preserved unchanged.
* feat: add "Update Available" banner with GitHub release check
Add a dismissible emerald banner that appears when a newer GitHub release
exists, so self-hosting users know an update is available. The banner
dismisses per-version (reappears for new releases).
- Create src/lib/version.ts as single source of truth from package.json
- Add /api/releases/check route with 1hr caching and graceful fallback
- Add UpdateBanner component mirroring LocalModeBanner pattern
- Add update state to Zustand store with localStorage persistence
- Fix hardcoded v2.0 in header-bar.tsx and 2.0.0 in websocket.ts
- Wire task board panel into Zustand store for real-time SSE updates
instead of local useState; add useSmartPoll fallback when SSE disconnects
- Fix priority enum mismatch: UI now uses 'critical' matching the Zod
validation schema instead of 'urgent'
- Add 'task.status_changed' to webhook EVENT_MAP so external consumers
receive status transition events
- Auto-advance task to 'done' column when aegis quality review approves,
broadcasting task.status_changed for real-time UI update
- Parallelize broadcast loop with Promise.allSettled so N agents execute
concurrently (~10s) instead of serially (N×10s)
Closes#73
Move page.tsx to [[...panel]] optional catch-all route so each panel
gets its own URL (e.g. /tasks, /agents, /settings). URL is the source
of truth — synced into Zustand via usePathname on every navigation.
Enables bookmarking, refresh persistence, deep-linking, and browser
back/forward.
Deduplicate gateway sessions server-side using sessionId as primary key,
falling back to agent:key composite for sessions without sessionId. This
prevents duplicate React keys when OpenClaw tracks cron runs under the
same session ID as the parent session.
Also adds EditTaskModal to the task board panel with inline edit button
in the task detail modal, and improves CreateTaskModal error handling.
Cherry-picked and adapted from PR #77 by @arana198.
Closes#80
Bug 1 (#78): Dockerfile HEALTHCHECK curled authenticated /api/status,
always got 401 in production. Changed to /login which is public.
Bug 2 (#78): Login hangs on HTTP deployments because secure=true cookie
is silently rejected. Now auto-detects protocol from x-forwarded-proto
header, only sets secure when request actually came over HTTPS.
Bug 3 (#78): Agent model field from OpenClaw 2026.3.x is {primary: "name"}
object instead of string, causing React error #31. Added normalizeModel()
helper and applied it in all WebSocket/session mapping code paths.
When no OpenClaw gateway is detected, Mission Control now automatically
switches to Local Mode — showing a clear info banner, greying out
gateway-dependent panels, and surfacing Claude Code session stats,
GitHub profile data, and subscription-aware cost display.
Changes:
- Add capabilities endpoint to detect gateway, Claude home, subscription
- Add dashboardMode/gatewayAvailable/subscription state to Zustand store
- Add dismissible LocalModeBanner component
- Grey out Agents/Spawn/Config nav items when no gateway
- Show blue "Local Mode" indicator instead of red "Disconnected"
- Dashboard shows local metric cards (sessions, projects, tokens, cost)
- Claude Code Stats panel with session/token/cost breakdown
- GitHub panel with repo stats, languages, star/fork counts
- Subscription detection from ~/.claude/.credentials.json
- Show "Included (Max plan)" instead of dollar cost for subscribers
- Fix token cost estimation (cache reads at 10%, not 100%)
- Sessions API falls back to local Claude session scanner
- Live feed injects session items in local mode
- Memory browser auto-creates data dir with fallback path
Cherry-picks three valuable fixes from @doanbactam's WebSocket refactor PR:
1. Feed item ID collision fix — prefix log IDs with 'log-' to avoid
React key collisions with activity IDs in the combined feed
2. Jittered reconnect backoff — add random jitter (0-50% of base) to
WebSocket exponential backoff to prevent thundering-herd reconnects
when multiple tabs reconnect after a server restart
3. Cron job deduplication + async I/O — deduplicate jobs.json entries
by name (keeps latest), prevent duplicates on add, and convert
sync file reads/writes to async to avoid blocking the event loop
Co-authored-by: Doan Bac Tam <24356000+doanbactam@users.noreply.github.com>
Security hardening:
- Fix timing-safe comparison bugs in webhooks.ts and auth.ts (was comparing buffer with itself)
- Harden rate limiter IP extraction — use rightmost untrusted IP from XFF chain with MC_TRUSTED_PROXIES support
- Add 12-char minimum password validation in Zod schema and runtime check
- Add Zod validation on PUT /api/tasks bulk status update
Webhook retry system (completing in-progress feature):
- Exponential backoff with circuit breaker in webhooks.ts
- POST /api/webhooks/retry endpoint for manual retry
- GET /api/webhooks/verify-docs endpoint for signature verification docs
- Scheduler integration for automatic retry processing
- Unit tests for signature verification and backoff logic
Local Claude Code session tracking:
- New claude-sessions.ts scanner parses JSONL transcripts from ~/.claude/projects/
- Extracts model, tokens, messages, cost estimates, active status per session
- Migration 020 adds claude_sessions table
- GET/POST /api/claude/sessions endpoint with filtering and aggregate stats
- Scheduler runs scan every 60s with MC_CLAUDE_HOME config
Quality improvements:
- Replace all console.error/warn with structured logger across 31 API routes
- Add Docker HEALTHCHECK directive
- Add vitest coverage config with v8 provider (60% threshold)
- Update README with new features, API docs, env vars, and roadmap items
- Fix E2E tests for password length and rate limiter IP changes
- Add openapi.json spec covering all 59 API routes (~95 operations)
- Serve spec at GET /api/docs (no auth required, cached)
- Add interactive Scalar API reference UI at /docs
- Allow unauthenticated access to /api/docs and /docs in middleware
- Add @scalar/api-reference-react dependency
- Add 3 E2E tests for spec validation and auth bypass
- Add `agents` field to tokens action=stats response (groups by agent
extracted from sessionId split on ':')
- Add new action=agent-costs returning per-agent stats, model breakdown,
session list, and daily cost/token timeline
- New AgentCostPanel with summary cards, pie chart, trend lines,
efficiency bars, and expandable ranking table
- Add nav-rail entry in OBSERVE group after Tokens
- Add ContentRouter case for agent-costs tab
- Add 5 E2E tests for the new API endpoints
- Sanitize session ID in control route to prevent command injection
via unsanitized URL params interpolated into shell commands
- Add mutationLimiter and structured logging to session control endpoint
- Install python3/make/g++ in Dockerfile deps stage for better-sqlite3
native addon compilation
- Handle missing public/ directory in Docker COPY with glob pattern
- Guard pino-pretty transport against missing devDependency at runtime