62 Commits

Author SHA1 Message Date
Aurora
1811418fd7 fix(workspace): add COOP+COEP (credentialless) headers so embedded HermesWorld WebGL keeps SharedArrayBuffer multithreading — matches standalone web client latency/perf instead of dropping to single-threaded in the iframe 2026-06-05 20:42:09 -04:00
Aurora
5271ca9ad3 PR #543: chat UIX/UX fixes — thinking indicators, message dedup, streaming stability (JohnGuidry)
Addresses #572 (double chat responses) + #561 (stuck Thinking indicator).
Adds optimistic-message-reinject hook, vite loadEnv→process.env bridge for SSR
bearer token, dedup + streaming stability. eslint --fix on touched files
(net lint errors 1700→1588). Build GREEN, test 33 fail/694 pass (zero regressions).
2026-06-05 06:01:21 -04:00
Aurora
611359b943 PR #550: surface kanban state in workspace dashboard (janishohbergs85-star) — addresses #570; restored null-guards in normalizeCron that PR removed 2026-06-05 03:55:58 -04:00
Eric
b69aa347ad fix: batch post-483 workspace follow-ups (#508)
Co-authored-by: Aurora release bot <release@outsourc-e.com>
2026-05-23 20:10:45 -04:00
Eric
4f75b5835c fix: batch remaining workspace bugfix slices (#483)
* chore: preserve pnpm approved builds

* fix(router): support runtime basepath override for reverse-proxy hosting

The TanStack router was created without a `basepath` option, so the same
built bundle could not be hosted under a path prefix (e.g. behind a
reverse proxy that mounts the app at `/workspaces/<id>/`). Hard refreshes
appeared to work because SSR runs at the proxy-stripped path, but
client-side navigation to dynamic routes such as `/chat/$sessionKey`
silently fell through to the catch-all `/$` route — rendering the
"404 — Not Found" page from inside the SPA.

Read an optional `window.__HERMES_WORKSPACE_BASEPATH__` global and pass
it through to `createRouter`. When unset, behavior is unchanged
(`basepath: '/'`). The value is normalized so callers can pass either
`/workspaces/abc`, `workspaces/abc`, or `/workspaces/abc/` without
upsetting TanStack's pathname matching.

This lets hosting layers inject a tiny inline script before the bundle
loads to mount the app at any path, without rebuilding.

* fix(chat): prevent stale thinking state after page refresh (closes #449)

Root cause: sessionStorage 'waiting' flags persisted across page refreshes
even for completed conversations. The Zustand store restored these stale
entries on mount, and the active-run API check cleared them async —
but there was a visible render window where the UI showed 'thinking'.

Fix:
1. Added activeRunCheckDone state that gates the waitingForResponse memo.
   While the active-run API check is pending, stale restored state is
   not trusted — the thinking indicator stays hidden until verification.
2. Added onCheckComplete callback to useActiveRunCheck hook that fires
   after the API check finishes (success or error), unblocking the gate.
3. Added a useEffect that detects restored stale waiting state and sets
   pendingVerifySessionKeyRef so the gate only applies to the key that
   needs verification — not to genuine active streams.

Test: e2e/chat-thinking-state.spec.ts injects a stale sessionStorage
entry before page load, then verifies no thinking indicator appears
and the stale entry is cleaned up by the API check.

* fix(chat): eliminate duplicate messages flicker on stream completion (closes #441)

Root cause: onDone handler used queryClient.invalidateQueries() which
triggers an async refetch. During the refetch window, mergeHistoryMessages
ran with stale cache data + realtime buffer, producing visible duplicates
(extra user message + blank line) for 1-2 seconds until refetch completed.

Fix: Directly merge realtime buffer into history cache via setQueryData(),
then clear buffer synchronously. Background refetch runs after for
consistency but doesn't block rendering.

* fix: restore hermes-config and config-patch API routes

The Aurora rename migration (efcb7d14) renamed hermes-config.ts to
claude-config.ts, but the frontend and routeTree.gen.ts still reference
the original paths. This caused all /api/hermes-config and /api/config-patch
requests to fall through to the SPA HTML fallback, breaking config saves
from the settings dialog and provider wizard with 'Failed to save' errors.

Restored by creating thin route files that delegate to the existing
handleHermesConfigGet/handleHermesConfigPatch handlers from
src/server/hermes-config-route.ts.

Fixes the settings dialog (hermes-config GET/PATCH) and provider wizard
(config-patch POST) config save flows.

* fix(server): add essential env vars to terminal session

* fix(swarm): worker card shows stale state after task completes

deriveWorkerState derived the badge from currentTask title substring
matching and markCheckpointResult never cleared currentTask on terminal
checkpoints, so a finished worker's card stayed permanently 'working'.

- swarm-dispatch.ts: clear currentTask on terminal checkpoint
  (checkpointStatus !== 'in_progress'), matching conductor-stop's reset
- operational-worker-card.tsx: deriveWorkerState reads authoritative
  checkpointStatus/state first, title heuristic only while in_progress
- swarm2-screen.tsx: pass checkpointStatus/state into the card

* fix(portable-history): replay authenticated portable chat history

* fix(config): keep legacy claude-config shim on shared handlers

* fix: harden splash hydration and docker uid mapping

* fix: keep seen update notes dismissed

* feat: consolidate workspace state under configurable state directory (closes #439)

Adds HERMES_WORKSPACE_STATE_DIR env var support, consolidating 5
scattered state files under a single configurable directory.

Changes:
- New src/server/workspace-state-dir.ts with getStateDir() utility
  honoring HERMES_WORKSPACE_STATE_DIR → HERMES_HOME/workspace →
  CLAUDE_HOME/workspace → ~/.hermes/workspace (fallback chain)
- Updated gateway-capabilities.ts (workspace-overrides.json)
- Updated mcp-presets-store.ts (mcp-presets.json)
- Updated mcp-hub-sources-store.ts (mcp-hub-sources.json)
- Updated mcp-tools-cache.ts (cache/mcp-tools.json)
- Updated knowledge-config.ts (knowledge-config.json)
- Removed 5 duplicated hermesHome() functions, replaced with shared
  getStateDir() import

Test: 6 vitest unit tests covering all env var priority combinations
(cherry picked from commit d6bebe0614b0c7b9015bac5e35d315a8450ac146)

* fix(conductor): surface native-swarm progress and harden worker startup

* feat(chat): safely render HTML message markup

* fix(chat): surface installed skills in slash autocomplete

* fix: add swarm runtime reset endpoint

* fix(conductor): mobile rendering — add overflow-y-auto, mobile bottom padding, OfficeView responsive height, tabbar fix

* fix(send-stream): preserve runs on client disconnect

* fix(profiles): skip profiles/default duplicate card

* fix: accept HERMES_AGENT_PATH override

* fix(profiles): allow disabling sticky active_profile writes

* fix: preserve workspace chat session routing

* fix(portable-history): skip replay when gateway session continuity is available

---------

Co-authored-by: Hermes Agent <hermes-agent@local.invalid>
Co-authored-by: jack <jack@hijak.dev>
Co-authored-by: Waylon Kenning <waylonkenning@Waylons-MacBook-Pro.local>
Co-authored-by: Michael Rodriguez <michael@rivercity-industries.com>
Co-authored-by: Vu Tran <baysao@gmail.com>
Co-authored-by: iltaek <iltaekkwon@gmail.com>
Co-authored-by: Aurora release bot <release@outsourc-e.com>
Co-authored-by: jonathanmalkin <jonathan.d.malkin@gmail.com>
Co-authored-by: KT-Hermes <ktadmin@kt-bot2.tekeis.net>
2026-05-19 16:27:10 -04:00
jarnodevries-byte
4f1bf50105 fix: harden workspace swarm prompt submission (#307)
Co-authored-by: Jarno de Vries <jarno@match-day.nl>
2026-05-05 15:23:27 -04:00
Aurora release bot
eb024d4378 fix(connection-status): return full capabilities payload in dev (#285)
The vite dev server intercepted /api/connection-status with a slim
inline shortcut handler that returned only {ok, mode, backend} \u2014
silently overriding the real route at src/routes/api/connection-status.ts
which returns the full ConnectionStatus payload.

Downstream feature gates (useFeatureCapability, useFeatureAvailable)
read .capabilities from the response. With the slim body, every
capability evaluated to undefined, so dev users got UI states that
looked like 'feature not available' even when the gateway was healthy
and exposing the API.

Fix: drop the inline shortcut entirely. The real route file already
caches via ensureGatewayProbed() (PROBE_TTL_MS), so the cost in dev
is negligible and the payload is correct everywhere.

Closes #285. Also drops the now-unused dashboard URL / token / cache
locals in vite.config.ts that were only used by the deleted handler;
the per-PR work that introduced them (#288, #289) was the
right diagnosis but the wrong fix \u2014 the real route was already
doing it correctly.
2026-05-04 02:00:30 -04:00
Aurora release bot
ce4fab300d fix(vite): point /api/sessions probe at dashboard URL, add auth header & ignore noise
Combines two community contributions and one local correction:

* PR #289 (Sanjays2402): probe /api/sessions on the dashboard URL
  (default :9119) instead of the agent URL (:8642). The agent does not
  serve /api/sessions, which produced a 404 every 15s. Adds a small
  cache so success/failure responses don't refetch every poll. Closes #276.

* PR #288 (Interstellar-code): send Authorization: Bearer
  $HERMES_API_TOKEN on the connection-status probes so a gateway
  secured with API_SERVER_KEY is detected correctly. Adds watch.ignored
  for .runtime/.tanstack/.omc/.omx/coverage/dist/etc. so these noisy
  internal paths don't fire spurious dev reloads.

* Local correction: did NOT add '**/routeTree.gen.ts' to watch.ignored.
  An existing regression test (src/router-route-resolution.test.ts)
  forbids that — ignoring the generated route tree breaks route HMR.
  The real cause of routeTree.gen.ts thrash is multiple concurrent
  vite dev servers writing to the same file (fixed earlier today).

Co-authored-by: Sanjays2402 <Sanjays2402@users.noreply.github.com>
Co-authored-by: Interstellar-code <Interstellar-code@users.noreply.github.com>
2026-05-04 01:43:53 -04:00
Interstellar-code
e8caa21b99 fix: correct vite dev proxy port and /cron route link (#283)
Fixes #276

Fixes #277
2026-05-04 01:41:52 -04:00
Interstellar-code
c021ef5fcc feat(mcp): replace /settings/mcp with full-featured /mcp page (catalog + marketplace + sources) (#231)
* feat(mcp): MCP server management page (Phase 1)

Implements the MCP management plan (.omc/plans/mcp-management.md) Phase 1
end-to-end on a single feature branch (PR1+PR2+PR3+PR4 collapsed):

- New `/mcp` route with capability gate + BackendUnavailableState fallback.
- New `/api/mcp` (GET list, POST create), `/api/mcp/test` (POST connection
  probe), `/api/mcp/discover` (POST tool discovery for a draft config),
  `/api/mcp/configure` (PUT enable/toolMode/include/exclude), and
  `/api/mcp/$name` (DELETE).
- Strict `mcp` capability probe in gateway-capabilities: hits `GET /api/mcp`
  directly and validates the body parses through `normalizeMcpList` —
  dashboard-up-but-route-missing returns false (resolves Open Question #4).
- Type split: read shapes in `src/types/mcp.ts` (client+server), write
  shapes in `src/types/mcp-input.ts` (server-only; secrets contained here).
- Runtime normalization layer `src/server/mcp-normalize.ts` mirrors the
  Skills `asRecord`/`readString`/`normalizeSkill` defense — strips
  unknown fields, coerces enums, masks secrets via `MASK_SENTINEL`,
  re-applies via `maskSecretsInPlace` before every `json(...)`.
- All write endpoints CSRF-checked via `requireJsonContentType`.
- Capability-off responses use `createCapabilityUnavailablePayload('mcp')`
  with `{ servers: [], total: 0, categories }` for GET (200) and 503 for
  writes — feature gates fall open without throwing.
- Static preset catalog (`src/screens/mcp/presets.ts`) with GitHub,
  Filesystem, Postgres, Slack, Linear; Catalog tab installs prefilled
  drafts through the same dialog flow.
- Screens: `McpScreen` (Installed/Catalog/All tabs + search + category
  filter), `McpServerCard` (status badge + Test/Edit/Delete + enable
  toggle), `McpServerDialog` (HTTP/stdio + auth + Discover + Save with
  bearer-token clear-on-submit).
- TanStack Query hooks (`useMcpServers`, `useTestMcpServer`,
  `useDiscoverMcpTools`, `useUpsertMcpServer`, `useConfigureMcpServer`,
  `useDeleteMcpServer`).

Tests (vitest):
- `src/server/mcp-normalize.test.ts` — 13 tests covering enum coercion,
  list-shape variants, malformed-entry drop, presence flags without
  echo, env/header masking by key hint, idempotency, test-result
  normalization, payload-string scanner.
- `src/routes/api/-mcp.test.ts` — 8 tests covering input validation,
  capability fall-open shape, CSRF gate (415 on non-JSON POST, pass on
  JSON, pass on GET), and the **secret echo guard**: a worst-case agent
  that echoes a submitted bearer token in body/env/headers must never
  surface the original string in the workspace response.

Build, lint, and the new test files are clean. Pre-existing unrelated
test failures on `local` (router-route-resolution, context-usage,
markdown math, slash-command-menu, chat-message-list, gateway-capabilities
env-source) are unchanged by this PR.

Worked with Interstellar Code

* fix(mcp): strip secret fields from client-safe McpClientInput

Architect review flagged that `McpClientInput` in `src/types/mcp.ts` (the
file explicitly designated for client+server read shapes with no secrets)
contained `bearerToken` and `oauth.clientSecret`, allowing the browser
bundle to import a secret-bearing type via the dialog component.

Resolves the type-split violation:
- `src/types/mcp.ts`: drop `bearerToken` and `oauth` from `McpClientInput`.
  Now strictly the browser-safe form payload, no secret fields.
- `src/screens/mcp/components/mcp-server-dialog.tsx`: hold `bearerToken`
  in ephemeral component-local `useState<string>` typed inline. Cleared
  on submit and on dialog open. No exported type carries the field.
- `src/screens/mcp/hooks/use-mcp-mutations.ts`: `useUpsertMcpServer`
  accepts `McpClientInput & { bearerToken?: string }` inline at the
  call-site, again with no exported secret-bearing type. Server route
  `parseMcpServerInput` re-validates and forwards to the agent.

The full server-side write shape (`McpServerInput` with secrets) remains
in `src/types/mcp-input.ts`, server-only.

Worked with Interstellar Code

* fix(mcp): block client imports of server-only mcp-input types

Add no-restricted-imports rule scoped to src/screens/** and
src/components/** that blocks importing @/types/mcp-input. That
file may carry unmasked secrets and is server-only — clients should
import McpClientInput from @/types/mcp instead.

Worked with Interstellar Code

* feat(mcp): wire /mcp into all sidebar/nav surfaces

Mirror the existing /skills registration across every nav and
command surface so the MCP screen is reachable from the dashboard
overflow grid, command palette, mobile hamburger drawer, mobile tab
bar, slash menu, search modal quick actions, and workspace shell
(active-tab tracking + mobile page title). Inspector panel gets a
parallel MCP tab that lists configured servers via /api/mcp.

Worked with Interstellar Code

* feat(mcp): catalog tab search, category badges, and nav coverage tests

Catalog tab now reuses the screen's search state to filter presets
by name/description, surfaces an empty-state when no presets match,
and renders each preset as a card with an Official Presets category
badge styled to match the skills-screen design vocabulary.

Tests:
- src/components/-mcp-nav.test.tsx: each modified nav file references
  the /mcp route (or registers an mcp tab id for inspector-panel)
- src/screens/mcp/-presets.test.ts: filtering MCP_PRESETS by query
  narrows results by name and description, returns full catalog for
  empty queries, and returns nothing for unknown queries

Worked with Interstellar Code

* feat(mcp): add MCP entry to chat-sidebar Knowledge group

The primary visible left rail (`chat-sidebar.tsx`) was missed by the
prior nav-coverage commit. Slot MCP between Skills and Profiles in
`knowledgeItems`, mirroring the McpServerIcon used elsewhere.

Worked with Interstellar Code

* feat(mcp): Phase 3 — live tool refresh, OAuth reauth, per-server SSE logs

- `useMcpServers`: enable refetchOnWindowFocus for live state.
- `McpServerCard`: per-card Refresh button (re-runs Test, updates
  discoveredToolsCount), Reauth button when authType === 'oauth' (uses
  new useMcpOAuth hook), Logs button (opens McpLogsDrawer).
- `use-mcp-oauth.ts`: opens auth URL in new tab, polls /api/mcp/test
  every 2s until status === 'connected' or 60s timeout. Returns
  mutation-style { start, isPending, isError, error, data }.
- `mcp-logs-drawer.tsx`: fixed-right slide-in drawer subscribing via
  EventSource to /api/mcp/<name>/logs. Newest-first, max 500 lines,
  auto-scroll, tear down on close (no zombie EventSource).
- `routes/api/mcp/$name.logs.ts`: SSE proxy with auth + capability
  gates. Capability-off → 503. Pattern follows chat-events.ts.
- Tests: 3 new for logs route (input validation, capability-off,
  auth gate); smoke test for useMcpOAuth shape.

Total tests: 24 passing (13 normalize + 8 mcp + 3 logs). Build clean.

Worked with Interstellar Code

* feat(mcp): localhost-only config-fallback transport (Phase 1.5)

Adds an `mcpFallback` capability that lets the workspace perform CRUD on
`config.mcp_servers` via the existing dashboard `/api/config` route when
the agent does not yet expose the new `/api/mcp*` runtime endpoints.

Gated to loopback-only deployments by `isLocalhostDeployment()` (both
URLs loopback AND HOST unset/loopback). Test/Discover/Logs return a
structured "not yet available" payload in fallback mode; the MCP screen
renders an amber banner so the limitation is visible.

Worked with Interstellar Code

* feat(mcp): full catalog + marketplace + sources manager (Phase 2-3.2)

Workspace-only end-to-end MCP catalog + marketplace replacing the static
presets.ts and the upstream /settings/mcp surfaces.

Phase 2 — File-backed catalog:
- assets/mcp-presets.seed.json + ~/.hermes/mcp-presets.json (atomic
  bootstrap via tmp+linkSync, mtime+ino+ctime+size cache, malformed-file
  preservation, schema validation: id regex, transport-specific fields,
  env key regex, https URLs, category allowlist, duplicate-id rejection,
  unknown-field warnings)
- src/server/mcp-input-validate.ts: shared parseMcpServerInput returning
  per-field {path, message} errors; promoted from inline definition
- src/routes/api/mcp/presets.ts GET handler

Phase 3.0 — Federated marketplace:
- src/server/mcp-hub/{cache,trust,index,types}.ts + sources/{mcp-get,
  local-file}.ts: Smithery registry adapter (replaces speculative
  registry.mcp.run NXDOMAIN), ETag/If-Modified-Since with 304 reuse,
  rate-limit handling, parallel Promise.allSettled across sources with
  8s per-source timeout, dedupe by source+id+name, fallback to
  local-file when remote degraded
- Trust hardening: shell metachar reject, transport allowlist, env-key
  regex, control-char + absolute-path attack defenses, inline-exec
  flag detection (-c, -lc, -e for sh/bash/python/node/perl/ruby)
- src/screens/mcp/components/install-confirmation-dialog.tsx: 2-click
  commit with full template preview (command/args/env masked) and
  AbortController on dismiss
- Disk persistence for tool-discovery cache (mcp-tools-cache.ts) +
  hermes-mcp CLI bridge (mcp-cli-bridge.ts) for live test/tool
  enumeration in fallback mode

Phase 3.2 — User-configurable sources:
- ~/.hermes/mcp-hub-sources.json schema (built-ins always present,
  protected from mutation; user can add HTTPS-only generic-json
  sources with trust+format)
- src/routes/api/mcp/hub-sources{,.$id}.ts CRUD with per-process mutex
  (read-modify-write race protection)
- generic-json adapter: SSRF guard (private/loopback/link-local/IPv6
  ULA all rejected after DNS resolution, redirects disabled), 5MB
  response-size cap (streaming read), trust hard-cap at 'community'
  for user-source entries, source field 'user:<id>' for dedupe
- src/screens/mcp/components/sources-manager-dialog.tsx UI

Polish:
- Placeholder detection at install confirmation (inline fill form
  blocks commit until /path/to/, <your-...>, empty *_TOKEN/_KEY/etc
  resolved)
- Test result UX hints when stdio Connection closed + placeholder args
  or http fetch failed + placeholder url
- Env-ref preserved in normalize (${VAR_NAME} no longer masked) +
  Edit dialog diagnostic

UI: Skills-pattern parity for /mcp screen (Tabs + Marketplace tab,
Switch primitive, Button primitives, DialogRoot/Content, primary-*
Tailwind classes matching skills-screen.tsx). Single-row toolbar
(tabs + search + filter). Removed All + Catalog tabs, kept Installed +
Marketplace.

Backend:
- gateway-capabilities probeMcp uses authenticated dashboardFetch
  (Codex MAJOR fix); probeMcpConfigKey + isLocalhostDeployment for
  mcpFallback capability
- routes/mcp.tsx route gate accepts mcp || mcpFallback
- mcp-normalize.ts headers.Authorization + env *_TOKEN/_KEY/_SECRET
  /_AUTH/_APIKEY auth detection upgrades authType to 'bearer'

Removed (replaced by /mcp):
- src/screens/settings/mcp-settings-screen.tsx (759 LOC)
- src/routes/settings/mcp.tsx
- src/routes/api/mcp/{servers,reload}.ts (orphaned endpoints; reload
  posted to gateway 404s)
- src/screens/mcp/presets.ts (static array, replaced by file-backed)
- settings-sidebar MCP nav entries (replaced by main /mcp route)

Tests: 263+ passing across 19+ MCP suites — input-validate, presets-
store, hub-cache/trust/unified-search, sources/{mcp-get,local-file,
generic-json}, hub-sources-store, mcp-tools-cache, ssrf-guard,
marketplace-install-confirmation, marketplace-placeholder-detection,
hub-search/-presets/-hub-sources route tests. Pre-existing 2
gateway-capabilities env-resolution failures unrelated.

Reviewers: Codex critic 4 passes (Phase 2 REJECTED → 8 fixes applied,
Phase 3.0 APPROVED-WITH-CHANGES → 4 fixes, Phase 3.2 REJECTED → 6
fixes including SSRF guard + response-size cap + concurrent-CRUD
mutex + trust cap). Architect approved final pass.

Worked with Interstellar Code
2026-05-03 12:49:28 -04:00
Rohit Sharma
6d9c283327 fix(chat): make long-running SSE streams survive silent agent processing (#195)
Five distinct issues were causing chat SSE streams to disconnect during
multi-minute silent processing windows on slow upstream providers (e.g.
Z.AI coding plan with rate limits and frequent connection drops).

Fixes in this commit:

- chat-screen.tsx active-run poller no longer false-positives on null
  run / queued / pending statuses; only fires streamFinish() on
  definitively terminal statuses (completed|failed|cancelled|error).

- vite.config.ts disables Node's default 5-minute requestTimeout for the
  dev server only (gated on command === 'serve'). Heartbeats handle
  keep-alive at the app layer; production servers keep their defaults to
  avoid slowloris exposure. Was killing any HTTP request older than 5min
  including healthy long-running SSE responses.

- use-streaming-message.ts AbortError path now clears hook state and
  invokes a new optional onAbort() callback instead of returning
  silently. Prevents UI flags (sending / waitingForResponse /
  pendingGeneration) from getting stuck when a stream is aborted by
  cross-session navigation, HMR unmount, or dev-server auto-restart.

- chat-screen.tsx wires onAbort to reset all sending/waiting flags so
  the composer unblocks immediately.

- models.ts now exposes streamAcceptedTimeoutMs / streamHandoffTimeoutMs
  in its response, sourced from workspace.stream_accepted_timeout and
  workspace.stream_handoff_timeout in ~/.hermes/config.yaml (env vars
  STREAM_ACCEPTED_TIMEOUT_MS / STREAM_HANDOFF_TIMEOUT_MS still
  override). Replaces the abandoned /api/stream-config route.

- chat-screen.tsx feeds those timeouts into useStreamingMessage so users
  can tune the no-activity windows via config.yaml without rebuilding.

- Removes orphan /api/stream-config route file (was returning HTML
  instead of JSON in dev because TanStack Start hadn't picked it up
  without a server restart; functionality moved to /api/models).

Refs upstream issue #195 for full root cause analysis.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit 941f8efa2b8881986c82205ebcb61b58187c4a08)
2026-05-01 11:14:34 -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
92c19c30a2 wip: swarm2 framework, sidebar nav, notification bridge, GH propagation
- Swarm + Swarm2 sidebar nav entries restored
- Swarm2 screens, routes, components, server modules
- API routes: swarm-roster, swarm-runtime, swarm-dispatch, swarm-checkpoint, swarm-orchestrator-loop, swarm-notifications, etc.
- Worker memory framework: swarm-memory, swarm-missions, swarm-lifecycle, swarm-foundation
- swarm.yaml roster reorganized by priority
- GH token propagation in dispatch + wrapper-side
- Multiple workspace shell + mobile nav additions
- Note: this snapshot includes some pre-PR-merge versions of files; needs reconciliation with origin/main for PRs #177, #168, #180, #165, #164
2026-04-29 10:21:58 -04:00
Eric
227be731a7 fix(#96): respect PORT env var for dev server (was hardcoded 3000) (#109)
The 'dev' and 'start:dev' scripts hardcoded --port 3000 on the CLI,
which collided with Baileys/WhatsApp bridges and other services that
also default to 3000. Users couldn't relocate the workspace without
editing package.json.

Changes:
- Drop --port from the CLI scripts; vite.config.ts now owns the port
- vite.config.ts reads process.env.PORT (default 3000) so users can run:
    PORT=4000 pnpm dev
- README snippet updated to mention the override
- Default stays at 3000 so every existing install, docker-compose file,
  and reverse-proxy rule keeps working

Fixes #96

Co-authored-by: Eric <eric@outsourc-e.com>
2026-04-22 14:43:17 -04:00
Eric
1867955693 fix(autostart): detect hermes-agent installed by Nous installer
User reported on X:
  'error: hermes agent not found clone it as a sibling directory or set
   hermes agent path in .env'

after running the fixed install.sh. The root cause is that Nous's installer
puts hermes-agent at ~/.hermes/hermes-agent/ (or installs a `hermes` binary
to ~/.hermes/bin/), but the workspace auto-start logic only looked at:
  - HERMES_AGENT_PATH env var
  - ../hermes-agent (sibling)
  - ../../hermes-agent (monorepo)

None of which match Nous's actual install layout. So every user installing
via the one-liner hit this error.

Changes in both vite.config.ts and src/server/hermes-agent.ts:
- Add ~/.hermes/hermes-agent and ~/hermes-agent to the candidate list
- Add a resolveHermesBinary() that finds ~/.hermes/bin/hermes or
  ~/.local/bin/hermes (Nous installer + fallback)
- Prefer launching `hermes gateway run` via the binary (canonical
  entrypoint) over reconstructing uvicorn against the source tree
- Fall back to uvicorn-from-source when only a directory is available
  (dev / cloned-in-place setups)
- Update the 'not found' error message to point at the installer URL
  instead of asking users to clone a sibling dir
- PATH for the spawned child now includes ~/.hermes/bin and ~/.local/bin
2026-04-20 16:38:09 -04:00
Eric
2590cf9bc5 feat: auto-discover local providers (Ollama, Atomic Chat)
- Probe localhost:11434 (Ollama) and localhost:1337 (Atomic Chat) on startup
- Auto-merge discovered models into /api/models response
- Auto-write custom_providers to config.yaml when new local backend detected
- New /api/local-providers endpoint for frontend discovery status
- 30s probe TTL with deduplication
- Logs provider online/offline state changes
2026-04-14 21:53:05 -04:00
Eric
47724ad303 fix(tasks): salvage kanban improvements and complete local task API (#57)
Co-authored-by: Aurora <aurora@MacBookPro.lan>
2026-04-13 20:47:22 -04:00
dontcallmejames
75800040f7 feat: reapply kanban task board on top of upstream v1.0.0
- 5-column kanban board: Backlog → Todo → In Progress → Review → Done
- Drag-and-drop, create/edit tasks, priority, assignees, tags
- Tasks link in sidebar nav
- Kanban proxy route in vite.config.ts for /api/hermes-tasks
2026-04-12 14:36:27 -04:00
Eric
fb17b5f86f feat: v1.0.0 — profiles, knowledge browser, MCP settings, skills hub upgrade, eslint, security contact update
New features:
- Multi-profile management (create, switch, rename, delete)
- Knowledge browser with document viewer
- MCP server settings screen
- Skills hub with marketplace search fallback
- Context usage tracking and display

Improvements:
- eslint added and auto-fixed (69 issues resolved)
- Settings dialog restructured (Agent, Smart Routing, Voice, Display sections)
- Navigation updated with Profiles tab across desktop/mobile
- Security contact updated to GitHub advisories + X DM
- .gitignore hardened (.runtime/, internal dev docs)
- Version bumped to 1.0.0

Build: clean | TypeScript: 0 errors | Tests: 4/4 passing
2026-04-10 01:49:13 -04:00
Eric
16181cc7de feat: activate context bar, fix token counting, port 3002 (#32)
- Render ContextBar in chat screen (was imported but never placed)
- Pass sessionId to context-usage API for accurate token data
- Count all tokens (cached + uncached) for real context window usage
- Model-aware max tokens (200k for Claude, 128k for GPT)
- Return model name in context-usage response
- Remove header border-b (context bar replaces separator)
- Remove context bar own border-b for clean look
- Change dev server port from 3000 to 3002

Co-authored-by: outsourc-e <eric@outsourc.e>
2026-04-08 20:11:28 -04:00
ClintMoody
4b15ee929f fix: client-side capability detection after SSR hydration (#19)
Replaces static isFeatureAvailable() with useFeatureAvailable() React hook that fetches from /api/gateway-status. Fixes enhanced features always showing 'unavailable' after client hydration. Credit: @ClintMoody
2026-04-03 10:28:07 -04:00
outsourc-e
1c8562a212 chore: remove internal docs, strip private refs, update README for hermes --gateway 2026-04-02 14:21:24 -04:00
outsourc-e
d02d8bab1c feat: portable mode - chat works without fork
- SSE streaming pipeline: send-stream → openaiChat → chat-store → UI
- Session key normalization: all portable mode uses 'main'
- Conversation history: last 20 messages sent with each request
- localStorage persistence: messages survive page refresh
- Thinking/content separation: Qwen3 reasoning → thinking events
- Auto-start guard: skip fork when HERMES_API_URL is external
- Legacy message normalization: ensureAssistantTextContent
- Streaming text handoff: completedStreamingTextRef bridges done→render
- Buffer cleanup disabled in portable mode (prevents message disappear)
- Test page: /test-streaming.html for direct SSE testing

Known issues:
- waitingForResponse handoff sometimes sticks (refresh fixes)
- Model pill shows wrong model name
- ClawSuite gateway banner unrelated
2026-03-31 22:03:27 -04:00
outsourc-e
05567a92fd Merge branch 'feat/ux-polish-v3-handshake'
# Conflicts:
#	pnpm-lock.yaml
#	src/routes/api/browser/navigate.ts
#	src/routes/api/browser/screenshot.ts
#	src/routes/api/browser/status.ts
#	src/routes/api/browser/tabs.ts
#	src/routes/api/gateway-config.ts
#	src/routes/api/gateway-discover.ts
#	src/routes/api/openclaw-update.ts
#	src/server/browser-monitor.ts
#	src/server/gateway-discovery.ts
#	src/server/gateway.ts
2026-03-19 20:16:44 -04:00
outsourc-e
96eb2655b0 feat: auto-start hermes-agent from pnpm dev + simplify connection screen
- vite.config.ts: resolveHermesAgentDir() finds hermes-agent via HERMES_AGENT_PATH env,
  ../hermes-agent sibling (standard README clone), or ../../hermes-agent fallback
- startHermesAgent() spawns uvicorn on pnpm dev start, reuses if already running,
  logs output to vite console, stops when dev server stops
- start-hermes.ts: same path resolution logic, polls health 10s instead of 2s,
  returns clear error + clone hint if hermes-agent not found, removed Eric-specific path
- connection-startup-screen.tsx: full rewrite — single useEffect, no stale closures,
  no settledRef vs useCallback dependency bugs. Simple: try once, succeed = dismiss,
  fail = show screen + poll every 3s. Start Server button kicks poll loop on success.
- webapi/app.py: CORS now covers localhost:3000-3010 by default + HERMES_CORS_ORIGINS env override
2026-03-19 15:37:32 -04:00
outsourc-e
a278685d97 chore: complete rebrand — rename all Gateway types, variables, comments to Hermes
Renamed: GatewayMessage→ChatMessage, GatewayAttachment→ChatAttachment,
GatewayChatState→ChatState, GatewayStatusDot→StatusDot, gateway-chat-store→chat-store,
use-gateway-chat-stream→use-chat-stream, gateway-restart-overlay→connection-overlay,
gateway-status-indicator→status-indicator, approvals-store moved to src/lib/

All internal variable names, query keys, localStorage keys, proxy paths,
comments, and event names renamed from gateway→hermes/server.

Only remaining 'openclaw' string: protocol client ID mapping (line 18, format-session-name.ts).
tsc clean.
2026-03-16 16:27:37 -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
outsourc-e
be30bd9a0f docs: fix env vars, rewrite features to match actual product, scrub stale references 2026-03-16 14:12:18 -04:00
outsourc-e
f3473d1ed5 fix: exclude routeTree.gen.ts from vite watch to prevent infinite reload loop 2026-03-16 13:36:02 -04:00
outsourc-e
1869a947b5 fix: loading loop (redirect to latest session not 'main'), relax unused var strictness for WIP 2026-03-16 12:27:35 -04:00
outsourc-e
bcb36f099b fix: allow all hosts for Tailscale/LAN access 2026-03-16 00:23:22 -04:00
outsourc-e
f1d292d977 feat: add vite dev server healthcheck endpoint 2026-03-14 14:23:29 -04:00
outsourc-e
ea9e377cb1 fix(workspace): forward API keys to daemon + decomposer logging (P0-3) 2026-03-14 12:50:48 -04:00
outsourc-e
a08d36e257 fix(workspace): deterministic DB path resolution (P0-2) 2026-03-14 12:50:07 -04:00
outsourc-e
cbbf0c86a2 fix(workspace): daemon auto-restart reliability (P0-1) 2026-03-14 12:48:59 -04:00
outsourc-e
2c79a9747d feat(workspace): stale daemon detection on startup (Sprint 4-5 Task 4) 2026-03-14 12:03:00 -04:00
outsourc-e
df96db6cd3 feat(workspace): daemon health monitor + restart button (Sprint 4-5 Task 3) 2026-03-14 12:01:12 -04:00
outsourc-e
fb2a9ba5f0 fix(workspace): retry storm guard + daemon auto-restart via tsx watch 2026-03-13 22:41:31 -04:00
outsourc-e
711d33cbe8 fix(workspace): proxy daemon requests through Vite so Tailscale access works 2026-03-13 01:48:57 -04:00
outsourc-e
85ec5daaf6 fix(workspace): daemon stability + nav pill error state isolation 2026-03-13 01:27:58 -04:00
outsourc-e
ab2634f7f1 fix(mobile): opaque nav pill + daemon auto-respawn on crash 2026-03-13 01:20:27 -04:00
outsourc-e
73ca1742c4 feat(electron+dev): autostart workspace daemon on app ready and vite dev server 2026-03-10 19:18:30 -04:00
outsourc-e
a8f002e5ec fix: allow Tailscale hostnames by default 2026-03-09 13:55:09 -04:00
Eric
f94cf7a942 fix: gateway WS proxy — route through ClawSuite server so any device works (#29)
Co-authored-by: Aurora <aurora@MacBookPro.lan>
2026-02-19 13:45:09 -05:00
Eric
a9772d200c feat: Mobile UX Polish v2 — context bar, session titles, composer, image preview (#28)
* feat: mobile UX polish — context bar, session titles, composer spacing, image preview

- Context bar: slim 3px bar with tap-to-reveal inline label (auto-hides 3s)
- Session titles: auto-friendly names (agent:main:main → Main Chat, heartbeat prompts → Main Chat)
- Title truncated to 20 chars with word boundary breaks, max-width 45vw
- Composer: tighter toolbar padding/gaps, model selector compact on mobile
- Attachment ✕ button always visible on mobile (hover-only on desktop)
- Tap-to-preview fullscreen image overlay (portaled to body)
- Message spacing: tighter gaps between messages on mobile
- User bubbles: compact padding on mobile
- Dashboard NowCard: friendly agent names
- Tasks widget: hides empty columns on mobile, wrapped in useMemo
- Logo tip: only shows on mobile
- PWA icons optimized + apple-touch-icon added

* fix: onboarding SSR hydration + allow empty gateway token

- onboarding-tour.tsx: added mounted state guard, return null during SSR
  prevents Joyride from accessing localStorage/DOM server-side
- use-onboarding-tour.ts: lazy localStorage read via useEffect
  eliminates server/client state divergence on hydration
- gateway.ts: remove hard requirement for token/password
  allows connecting to gateways without auth (e.g. nanobot on port 18790)
  device identity signature handles authentication instead
- gateway-setup-wizard.tsx: mark token as optional, add nanobot port hint

Reported-by: @absol_89 (Tharshan)

* fix: remove pull-to-refresh (buggy on mobile) + gateway save timeout 5s→15s

- Remove pull-to-refresh from dashboard and chat message list
- Increase gateway config save timeout from 5s to 15s
- Show 'Config saved. Reconnecting...' instead of timeout error
- Remove onPullOffsetChange prop from chat-screen
- Add onRefresh prop to chat-message-list for manual refresh
- Add mobile viewport detection for responsive padding
- Clean up unused streaming state variables

* feat: mobile agent hub sheet + tab bar improvements + chat header polish

- Add slide-up mobile sheet for agent view panel (replaces desktop sidebar)
- Tab bar: swipe-up gesture to reveal when hidden by keyboard
- Chat header: agent model + connection status display
- Chat empty state: responsive padding for mobile
- Orchestrator avatar: accept className prop
- Onboarding tour steps: minor cleanup

* chore: fix all 40 pre-existing TypeScript errors (0 remaining)

- Remove unused imports/variables across 15 files (TS6133/TS6192)
- Fix update-notifier type narrowing for 'done' state (TS2367)
- Fix route type assignments with string casts for /chat/main (TS2322)
- Fix gateway.ts global declaration syntax (TS2488)
- Remove invalid tooltipClose Joyride style property (TS2353)
- Remove stale skills-screen 'featured' tab comparison (TS2367)
- Remove unused @ts-expect-error in vite.config.ts (TS2578)
- Clean up dead code: getMessageTimestamp, normalizeStatusPayload, etc.

No functionality changes. All fixes verified with npx tsc --noEmit.

* fix: auto-refresh model list cache every 30s

Previously, configured models were cached forever in memory, requiring
a server restart to pick up new models added to openclaw.json config.

Now uses a 30s TTL so model list updates are reflected automatically.
Exports invalidateCache() for manual refresh if needed.

* feat: show all user-configured models in model switcher

Models defined in openclaw.json config but not auto-discovered by the
gateway's models.list RPC now appear in the model switcher. This ensures
newly added models (like claude-sonnet-4-6) show up without waiting for
gateway discovery.

Also exports getConfiguredModelsFromConfig() for direct config reads.

* fix: new chat creates unique thread ID instead of routing to main

* feat: telegram-style slash command autocomplete in chat composer

* feat(dashboard): add WidgetShell component + wiggle/shimmer CSS

- WidgetShell: unified iOS-style widget container with size variants
  (small/medium/large), glass background, press states, edit mode jiggle,
  loading skeleton, and error state
- WIDGET_SIZE_SPAN export for use in widget-grid CSS grid layout
- Added animate-shimmer utility (skeleton loading)
- Added animate-wiggle keyframe (iOS jiggle edit mode)
- tsc --noEmit: 0 errors

---------

Co-authored-by: Aurora <aurora@MacBookPro.lan>
2026-02-17 22:50:47 -05:00
Eric
614f365067 fix: Docker runtime env vars (process.env was baked at build time)
Root cause: Vite's 'define' config replaced ALL process.env references
with empty objects in both client AND server bundles. TanStack Start's
environment-based builds don't use the old isSsrBuild flag, so the
client-only guard never worked.

Fix:
- Removed blanket process.env replacement from top-level define
- Added client-only transform plugin that replaces process.env only
  in client bundles (browser has no process.env)
- Server bundles now keep real process.env for Docker runtime env vars
- Gateway config save no longer fails on read-only containers (EACCES)

Tested: Docker container reads CLAWDBOT_GATEWAY_URL and TOKEN from
runtime env vars, /api/ping returns {ok:true}
2026-02-13 22:19:17 -05:00