19 Commits

Author SHA1 Message Date
Eric
cd6115b2fc fix: consolidate verified workspace issue sweep (#432)
* fix(start): use server-entry wrapper for production

* fix(swarm): reconcile oneshot checkpoints and ignore phantom blockers

* fix(profiles): sync editable descriptions from profile config

* fix: show cron jobs across Hermes profiles

* fix(capabilities): clarify dashboard-backed API detection

* feat: make Conductor use native Swarm fallback

Treat Workspace-native Swarm as the official Conductor fallback when the dashboard mission API is unavailable. Preserve dashboard-first dispatch, native status/cancel handling, provider-neutral setup docs, and regression coverage for gateway capability detection, swarm health, roster/profile handling, and native Conductor responses.

* fix(usage-meter): reposition menu trigger for better alignment

- Adjusted the position of the menu trigger in the usage meter component to enhance layout consistency and user experience.

fix(chat-panel): adjust position of chat panel toggle button

- Updated the positioning of the chat panel toggle button to improve visibility and accessibility by changing its bottom and right offsets.

* fix(stt): wire Groq/OpenAI voice transcription into chat

* Fix Workspace Kanban loopback dashboard link

* fix(update): do not open historical release notes on startup

* fix(chat): clear stale thinking runs reliably

* fix(dashboard): trust sessions endpoint for status

* fix(settings): address review — local default, OAuth lifecycle, validation

* fix(dashboard): always scrape live session token from HTML

* fix(chat): avoid portable history replay on bound sessions

* fix(settings): remove dead smart routing controls

* fix(tasks-api): guard against HTML catch-all in probeBackend

The /api/hermes-tasks route was renamed to /api/claude-tasks in commit
efcb7d14, but the probe logic still listed the old route as a candidate.
When probed, the SPA catch-all returned a 200 HTML response instead of
a 404, so probeBackend() treated it as a valid (empty) backend and then
failed when the actual task fetch threw.

Fixes:
- probeBackend() now checks Content-Type: application/json and returns
  -1 for non-JSON responses, so future route renames degrade gracefully.
- resolveBackend() now only selects hermes if hermesCount > 0, defaulting
  to claude-tasks (the active backend post rename) when hermes is absent.

* fix(terminal): default cwd to ~ and fallback if path missing

PTY helper chdir fails when ~/.hermes is absent (common in Docker).
Default shell cwd to home; server falls back to HOME if cwd does not exist.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(settings): satisfy lint on custom providers UI

* fix(docker): add -m flag to useradd so workspace home dir is created

Without -m, the system account has no /home/workspace directory.
The auth middleware tries to write the session store at
/home/workspace/.hermes/workspace-sessions.json; mkdirSync fails with
EACCES because /home/ is root-owned (755), causing the 'Failed to
persist session store' warning and a 500 on every authenticated route.

Adding -m causes useradd to create and chown /home/workspace correctly
so the session store can be written on first login.

* fix(tasks): preserve real session links and restore task launch flow

* fix(launchd): install macOS plist from server-entry template

* fix(docker): expose dashboard API and persist workspace volumes

* fix(jobs): serialize deliver targets for cron API

* Make Hermes Workspace installable as PWA

* chore(deps): pin direct tanstack versions

* feat: align semantic Hermes swarm agents

Add semantic swarm roster metadata, profile/tool/skill docs, shared semantic worker ID validation, focused roster regression coverage, and one-shot checkpoint capture for dispatch smoke tests.

* fix(conductor): pass through sessionKeyPrefix from portable spawn result

sessionKeyPrefix was hardcoded to null in conductor-spawn.ts, breaking
async session resolution when the dashboard backend returns a prefix.
Now mirrors the sessionKey pattern and passes through the value from
the spawn result.

Co-authored-by: Hermes Agent

* feat(swarm): bridge workspace kanban to native Hermes

* fix(chat): keep portable main pinned without breaking resolved sessions

* Add Windows startup script for Hermes Workspace

Document PowerShell usage for launching and restarting gateway + workspace via WSL tmux.

Co-Authored-By: Oz <oz-agent@warp.dev>

* fix(config): name Hermes Agent in restart notice

* fix(swarm): reconcile aggregate semantic worker exports

---------

Co-authored-by: Aurora release bot <release@outsourc-e.com>
Co-authored-by: motoki takahashi <motokitakahashi@motokinoMac-mini.local>
Co-authored-by: Vicky Wonder <vicky@openclaw.ai>
Co-authored-by: Vitaliy Isikov <visikov+supagoku@gmail.com>
Co-authored-by: Hermes Agent <hermes-agent@local>
Co-authored-by: Nikolay Mohr <nikomohr96@gmail.com>
Co-authored-by: Niko Mohr <niko@friendsfromcollege.de>
Co-authored-by: wtchronos <262830926+wtchronos@users.noreply.github.com>
Co-authored-by: Dak0verflow <dakotaferris@gmail.com>
Co-authored-by: norema <mamadou.marone.19@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: daoyuan <ludaoyuan1989@gmail.com>
Co-authored-by: firemountain <firemountain@gmail.com>
Co-authored-by: RAZSOC Local <razsoc@local>
Co-authored-by: Waylon Kenning <waylonkenning@Waylons-MacBook-Pro.local>
Co-authored-by: Kublai <kublai@kublai.local>
Co-authored-by: justa <justa@local>
Co-authored-by: Oz <oz-agent@warp.dev>
2026-05-13 22:34:42 -04:00
Eric
2b8093b556 fix(docker): start Hermes Agent gateway in compose (#385)
The hermes-agent image's default entrypoint is the interactive CLI which
exits immediately under `docker compose up -d`, causing the gateway to
appear absent and the Workspace healthcheck/connection to fail with
"Could not reach Hermes gateway". Override the command to `gateway run`
so the long-running API/health server starts.

Reproducible without this fix: a fresh `docker compose up -d` against
upstream main fails with the symptoms reported in #360 across several
users (different OSes), and the only working remedy was for users to
manually patch their compose with `command: gateway run`.

Closes #360

Co-authored-by: Aurora release bot <release@outsourc-e.com>
2026-05-07 19:56:46 -04:00
Eric
af50de716e chore: rename leftover CLAUDE_* env vars to HERMES_* (back-compat preserved) (#273)
The 2026-05-01 codename rename swept most of the repo from 'Claude' to
'Hermes' but left a few env vars and README copy that still referenced
the old name. Users on fresh installs were configuring HERMES_PASSWORD
based on the docs but the auth middleware only read CLAUDE_PASSWORD,
silently bypassing the guard.

Changes:
- src/server/auth-middleware.ts: read HERMES_PASSWORD first, fall back
  to CLAUDE_PASSWORD for back-compat with pre-rename setups.
- server-entry.js: same fallback for HERMES_PASSWORD +
  HERMES_ALLOW_INSECURE_REMOTE. Error messages updated to point at the
  new names.
- README.md:
  - Drop the misleading 'v2 zero-fork = full feature parity' framing;
    call out that Conductor specifically requires an upstream dashboard
    plugin not yet shipped (per #262), with a link.
  - Theme list updated to current names (Hermes / Nous / Bronze /
    Slate / Mono \u2014 the v2.1 rename) instead of the old 'Official /
    Classic' labels.
  - Replace CLAUDE_PASSWORD / CLAUDE_ALLOW_INSECURE_REMOTE references
    with HERMES_* primary names + back-compat note.
  - Add HERMES_API_TOKEN to the security env-var list (previously
    undocumented despite being honored by the gateway-capabilities probe).
  - Inline note on the avatar PNG asset name being retained for cache
    stability \u2014 the 'claude-avatar' filename is intentional.
- .env.example: HERMES_PASSWORD + HERMES_ALLOW_INSECURE_REMOTE primary
  names with legacy notes.
- docker-compose.yml: HERMES_PASSWORD: ${HERMES_PASSWORD:-${CLAUDE_PASSWORD:-}}
  so existing compose files that set CLAUDE_PASSWORD keep working while
  new files use HERMES_PASSWORD.

Build + auth-middleware tests pass.

No public-facing breaking change: every previous CLAUDE_* env var still
resolves correctly through the back-compat fallbacks.

Co-authored-by: Aurora release bot <release@outsourc-e.com>
2026-05-03 13:15:37 -04:00
Aurora release bot
7fe6f4a4bb fix(branding): restore Hermes naming across GitHub surfaces 2026-05-01 10:55:01 -04:00
Aurora release bot
efcb7d144e chore(rename): migrate legacy 'Hermes' codename bytes to canonical 'Claude' across repo
- Rewrites all Claude/claude/CLAUDE -> Hermes/claude/CLAUDE
- Renames 31 files (hermes-*.ts -> claude-*.ts, hermes-*.png -> claude-*.png, etc.)
- Renames 1 directory (src/routes/api/hermes-proxy -> claude-proxy)
- 254 files content-modified, 2681 byte sequences replaced
- Build passes, no new test regressions (pre-existing failures unchanged)
- Adds skills-bundle/ to gitignore + vitest exclude to keep test scope clean
2026-05-01 01:00:06 -04:00
Eric
41a9d1a4d0 security: harden auth/files/deployment defaults (#121, #122, #123, #124, #125) (#133)
Addresses the 5 security findings from @kiosvantra's audit (thank you!).

## #121 — Path traversal via naive startsWith()
src/routes/api/files.ts: ensureWorkspacePath now uses path.relative()
to enforce the workspace boundary. The previous string-prefix check
accepted sibling paths (e.g. /root/.hermes2 when root is /root/.hermes).
Added regression tests in src/routes/api/-files.test.ts.

## #122 — Deployment defaults expose control plane
server-entry.js: default HOST to 127.0.0.1. If HOST is non-loopback
and HERMES_PASSWORD is unset, the server refuses to start with a
clear banner explaining the fix. An explicit
HERMES_ALLOW_INSECURE_REMOTE=1 escape hatch is available for operators
who understand the risk.
docker-compose.yml: gateway defaults to 127.0.0.1 (no host binding),
workspace publishes on 127.0.0.1:3000 and passes HERMES_PASSWORD /
COOKIE_SECURE / TRUST_PROXY through.

## #123 — Session cookie missing Secure
src/server/auth-middleware.ts: createSessionCookie() now appends
Secure by default in production (and when COOKIE_SECURE=1 overrides).
Docs clarify when dev-HTTP exemption is safe.

## #124 — Dashboard token scraped from HTML
src/server/gateway-capabilities.ts: fetchDashboardToken() now prefers
an explicit HERMES_DASHBOARD_TOKEN (or HERMES_API_TOKEN) env bearer.
The HTML-scrape path remains as a logged fallback for existing
deployments, with a deprecation warning pointing at #124. This removes
the brittle trust boundary in production.

## #125 — x-forwarded-for trusted unconditionally
src/server/auth-middleware.ts + src/server/rate-limit.ts: both IP
resolvers now ignore forwarded headers unless TRUST_PROXY=1 is set.
Without that opt-in, clients cannot spoof local classification or
rotate rate-limit keys via x-forwarded-for. Added regression tests.

## Env + docs
.env.example: new Security section documenting HOST, HERMES_PASSWORD,
COOKIE_SECURE, TRUST_PROXY, HERMES_DASHBOARD_TOKEN, and the bypass.
README.md: Security section updated to reflect the new posture and
credit the audit.

## Verification
- tsc --noEmit: clean
- vitest: 43/43 pass (added 16 new tests across files, auth-middleware,
  rate-limit)
- Fail-closed guard verified manually:
    HOST=0.0.0.0                        \u2192 exit 1 with banner
    HOST=0.0.0.0 HERMES_PASSWORD=x      \u2192 starts
    HOST=0.0.0.0 HERMES_ALLOW_INSECURE_REMOTE=1 \u2192 starts with warn
    HOST=127.0.0.1                      \u2192 starts

Closes #121, #122, #123, #124, #125

Co-authored-by: Eric <eric@outsourc-e.com>
2026-04-23 21:02:59 -04:00
Eric
d357005506 feat(docker): default docker compose to pre-built images (#82) (#83)
Swap docker-compose.yml from local builds to pulling the official
upstream images by default. No more 'wait 10 minutes for git clone +
pip install + uv venv' on first run.

- hermes-agent   -> nousresearch/hermes-agent:latest (upstream)
- hermes-workspace -> ghcr.io/outsourc-e/hermes-workspace:latest (our GHCR)

Also:
- Persist agent state to a named 'hermes-data' volume mounted at /opt/data
  (config, sessions, skills, memory, creds survive container recreation).
- Add docker-compose.dev.yml overlay so contributors can still build from
  source via: docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build
- Harden the healthcheck to CMD-SHELL so exit codes propagate.
- README + CHANGELOG updated to match.

Closes #82.

Co-authored-by: Aurora <aurora@outsourc-e.dev>
2026-04-20 23:08:59 -04:00
Eric
62ffc6a2d5 docs: ANTHROPIC_API_KEY is NOT required — hermes-agent is provider-agnostic
User on Discord reported our docs saying ANTHROPIC_API_KEY is required.
It's not — hermes-agent supports Anthropic, OpenAI, OpenRouter (incl. free
models), Google, local Ollama/LM Studio, etc. Users only need the key for
the provider they actually picked in `hermes setup`.

Also replaced the 'pip install hermes-agent' references that snuck in — the
package isn't on PyPI, it installs from source via Nous's official script.

Changes:
- .env.example: list all common provider keys, all commented out, users
  uncomment whichever they use
- docker-compose.yml: pass through ANTHROPIC / OPENAI / OPENROUTER / GOOGLE /
  GROQ / MISTRAL keys (all optional, whichever is set wins)
- README.md: remove 'ANTHROPIC_API_KEY required' claim, replace pip install
  references with the Nous installer path, generalize Docker troubleshooting
  to match any provider
- FEATURES-INVENTORY.md: list all supported provider env vars
2026-04-20 15:34:58 -04:00
Eric
3a3c521a35 feat(docker): document HERMES_API_TOKEN / API_SERVER_KEY pairing
Closes #77 — nekopep reported workspace couldn't authenticate to a gateway
exposed on 0.0.0.0 with API_SERVER_KEY set. Workspace already supports
HERMES_API_TOKEN (added previously) but it wasn't documented.

- Document HERMES_API_TOKEN in .env.example with the matching API_SERVER_KEY
  relationship and usage notes.
- Wire through API_SERVER_KEY / API_SERVER_HOST / API_SERVER_ENABLED in
  docker-compose.yml so both services pick up the secret from a single
  .env value.
- HERMES_API_TOKEN on the workspace side now defaults to the same
  API_SERVER_KEY so Docker Compose works out of the box.
2026-04-20 15:03:33 -04:00
Eric
c18dc7280c fix(#36,#48): improve Docker docs + enhanced mode messaging
- docker-compose.yml: document enhanced vs portable mode, point to fork
- feature-gates: explain that enhanced features need outsourc-e/hermes-agent
- gateway-capabilities: update upgrade instructions to reference fork

Closes #36 (already fixed in Dockerfile, now documented)
Addresses #48 (better UX for portable mode users)
2026-04-12 13:09:08 -04:00
Joey
59f24e333a docs: fix Docker setup instructions and add troubleshooting guide (#21)
Clarifies Docker quickstart, required ANTHROPIC_API_KEY setup, gateway command updates, and troubleshooting for auth/connectivity issues. Credit: @joeynyc
2026-04-03 14:37:55 -04:00
outsourc-e
fc3f64880e feat: Docker Compose + Codespaces setup — one command to run everything 2026-03-18 13:25:10 -04:00
outsourc-e
e8baad35b7 chore: Hermes Workspace v0.1.0 — initial open-source release 2026-03-16 16:18:20 -04:00
outsourc-e
88c5d43aef chore: final scrub — fix CONTRIBUTING, docker-compose, version 0.1.0, remove all CLAWDBOT/OpenClaw env vars
- CONTRIBUTING.md: rewritten for Hermes (pnpm, HERMES_API_URL, no gateway)
- docker-compose.yml: HERMES_API_URL/PASSWORD/ALLOWED_HOSTS only
- vite.config.ts: CLAWDBOT_GATEWAY_URL → HERMES_API_URL
- paths.ts: rewritten for ~/.hermes/
- workspace.ts, files.ts: removed OPENCLAW_WORKSPACE_DIR fallback
- package.json: version 0.1.0 (not 4.0.0)
- README.md: v4.0 → 0.1.0, removed ClawSuite version references
- .gitignore: ensure .env/.env.local excluded

Zero ClawSuite/OpenClaw/CLAWDBOT references in tracked files.
2026-03-16 16:05:32 -04:00
outsourc-e
82c3f70975 chore: deep cleanup — remove all ClawSuite/OpenClaw bloat, dead screens, workspace daemon, gateway UI
Deleted:
- 30+ stale .md files (specs, audits, roadmaps)
- docs/archive/ directory
- data/specs/, data/agent-hub-architecture-report.md
- workspace-daemon/ (entire ClawSuite orchestration daemon)
- release/ (Electron builds)
- Screens: activity, costs, cron, tasks, gateway (kept approvals stub)
- Components: gateway-setup-wizard, openclaw-update-notifier, update-notifier,
  compaction-notifier, fallback-banner, exec-approval-toast, gateway-restart-overlay
- API routes: gateway/*, cloud/*, cron/*, browser/*, debug/*, events/*,
  workspace/* (orchestration), cli-agents, system-metrics, diagnostics, etc.
- Server: debug-analyzer, activity-stream, activity-events, workspace-proxy,
  exec-approval-store, browser-monitor, gateway-stream, cron
- Stores: mission-store, mission-event-store
- Hooks: use-agent-view, use-task-reminders

Stubbed (preserves chat functionality):
- approvals-store (no-op, chat-screen imports it)
- use-research-card (no-op)
- research-card component (returns null)
- gateway-restart-overlay (passthrough)

Rebranded:
- CONTRIBUTING.md, docker-compose.yml, vite.config.ts, test-redaction.ts
- Env vars: HERMES_WORKSPACE_DIR with OPENCLAW fallback

213 files changed, -56,503 lines. tsc clean.
2026-03-16 15:33:03 -04:00
outsourc-e
d3a59225dc chore: full ClawSuite/OpenClaw reference scrub — rebrand to Hermes Workspace 2026-03-16 14:57:58 -04:00
Eric
c1ef8bd84b polish: chat experience + settings screens — enterprise UX audit fixes
## Chat Experience Fixes

### Code Blocks
- Added horizontal scroll wrapper for long code lines
- Sticky line numbers when scrolling horizontally
- Improved spacing (my-2) for better visual separation
- Enhanced code block text color in fallback mode

### Composer
- Added Cmd+Enter keyboard shortcut to send
- Clear draft button (X icon) when draft exists
- Improved placeholder text with hint: 'Ask anything... (⌘↵ to send)'
- Made model selector responsive (mobile-friendly width)
- Added tooltip to model button showing full model name

### Failed Messages
- Added retry button for failed messages
- Failed messages show red border and background (bg-red-50/50)
- Better visual feedback for queued vs failed states

### Long Messages
- Added max-height protection (600px user, 800px assistant)
- Overflow-y-auto for very long content

### Narration Messages
- Improved collapsible UI with better border and background
- Clear expand/collapse arrow indicator
- Max-height (400px) with scroll for long narration

### Streaming
- Enhanced streaming cursor (simple pulsing dot)
- Better typing indicator with avatar circle and clearer text
- Added role='status' and aria-live='polite' for accessibility

### Loading States
- Added skeleton loader for initial message load
- Animated placeholder messages while loading

### Tool Sections
- 'Show All' button changes to '✓ Expanded' when clicked
- Better hover states and accessibility labels

### Images & Attachments
- Increased max height (48px → 64px) for better visibility
- Added lazy loading for performance
- Added max-w-full to prevent overflow
- w-auto for proper aspect ratio preservation

### Markdown
- Improved inline code sizing (py-1 → py-0.5, text-sm → text-[0.9em])
- Better code block spacing

### Accessibility
- Added aria-labels throughout
- Improved keyboard navigation
- Better focus management

## Settings Screens Fixes

(Previous settings screen changes preserved)
2026-02-13 17:00:12 -05:00
Eric
6bfa98b5a5 fix: Docker build — add .npmrc for peer dep resolution + password env
- .npmrc with legacy-peer-deps=true fixes npm ci failure
  (react-joyride → react-floater requires React 15-18, we use React 19)
- Added CLAWSUITE_PASSWORD to docker-compose.yml
- Verified locally: npm ci , npm run build , node dist/server/server.js 
  - / redirects to /dashboard (307)
  - /dashboard renders full HTML
  - /api/auth-check returns correct JSON
  - /manifest.json serves PWA manifest
  - /sw.js serves service worker
2026-02-13 15:21:54 -05:00
Eric
be7f43980f feat: add Dockerfile, docker-compose.yml, and .dockerignore
Multi-stage build (node:22-alpine). Non-root user. Connects to
host gateway via host.docker.internal by default.

Usage:
  docker compose up --build

Requested by @tharshan_09
2026-02-13 14:40:35 -05:00