Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -283,3 +283,34 @@ The BFF layer handles API proxy (with path rewriting), SSE streaming, file uploa
## License

[MIT](./LICENSE)

## Configuration

### API Server Key for Jobs API

Web UI requires `API_SERVER_KEY` to authenticate with Hermes Gateway's Jobs API.

**For default profile**, create `~/.hermes/.env`:
```bash
API_SERVER_KEY="your-api-server-key"
```

**For other profiles**, create `~/.hermes/profiles/<profile-name>/.env`:
```bash
API_SERVER_KEY="your-api-server-key"
```

The API key is configured in `~/.hermes/config.yaml`:
```yaml
platforms:
api_server:
enabled: true
key: "your-api-server-key" # Copy this value to .env
extra:
host: 127.0.0.1
port: 8642
```

### Why is this needed?

Web UI's `gateway-manager.ts` reads `API_SERVER_KEY` from `.env` file to authenticate proxy requests to Hermes Gateway's `/api/jobs` endpoint. Without this configuration, the Jobs page will return `Invalid API key` error.
7 changes: 4 additions & 3 deletions packages/server/src/db/hermes/session-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,12 @@ export function createSession(data: {
model?: string
title?: string
workspace?: string
source?: string
}): HermesSessionRow {
const now = Math.floor(Date.now() / 1000)
if (!isSqliteAvailable()) {
return {
id: data.id, profile: data.profile || 'default', source: 'api_server',
id: data.id, profile: data.profile || 'default', source: data.source || 'api_server',
user_id: null, model: data.model || '', title: data.title || null,
started_at: now, ended_at: null, end_reason: null,
message_count: 0, tool_call_count: 0,
Expand All @@ -150,8 +151,8 @@ export function createSession(data: {
const db = getDb()!
db.prepare(
`INSERT INTO ${SESSIONS_TABLE} (id, profile, source, model, title, started_at, last_active, workspace)
VALUES (?, ?, 'api_server', ?, ?, ?, ?, ?)`,
).run(data.id, data.profile || 'default', data.model || '', data.title || null, now, now, data.workspace || null)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
).run(data.id, data.profile || 'default', data.source || 'api_server', data.model || '', data.title || null, now, now, data.workspace || null)
return getSession(data.id)!
}

Expand Down
3 changes: 2 additions & 1 deletion packages/server/src/services/hermes/session-sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ async function syncProfileSessions(profile: string): Promise<{
try {
// Use listSessionSummaries to get aggregated session chains
// This returns only root sessions with aggregated stats from the entire chain
const summaries = await listHermesSessionSummaries('api_server', 10000, profile)
const summaries = await listHermesSessionSummaries(undefined, 10000, profile)

logger.info(`[session-sync] profile '${profile}': found ${summaries.length} aggregated session chains`)

Expand All @@ -77,6 +77,7 @@ async function syncProfileSessions(profile: string): Promise<{
id: newSessionId,
profile,
model: hermesSession.model,
source: hermesSession.source,
title: hermesSession.title || undefined,
})

Expand Down