fix(docker): resolve container networking and DB compatibility issues (#560)
- Auto-detect Docker container environment and use service name 'hermes-agent' as default host instead of 127.0.0.1 - Replace hardcoded column names with SELECT * in session DB queries to compat with older Hermes agent state.db schemas - Remove unused UPSTREAM env var from docker-compose.yml - Include err.message in syncFromHermes failure logs - Add group chat rule to prevent self-mentioning Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -32,7 +32,6 @@ services:
|
|||||||
- hermes-agent-src:/opt/hermes
|
- hermes-agent-src:/opt/hermes
|
||||||
environment:
|
environment:
|
||||||
- PORT=${PORT:-6060}
|
- PORT=${PORT:-6060}
|
||||||
- UPSTREAM=${UPSTREAM:-http://hermes-agent:8642}
|
|
||||||
- HERMES_HOME=/home/agent/.hermes
|
- HERMES_HOME=/home/agent/.hermes
|
||||||
- HERMES_BIN=${HERMES_BIN:-/opt/hermes/.venv/bin/hermes}
|
- HERMES_BIN=${HERMES_BIN:-/opt/hermes/.venv/bin/hermes}
|
||||||
- AUTH_DISABLED=${AUTH_DISABLED:-false}
|
- AUTH_DISABLED=${AUTH_DISABLED:-false}
|
||||||
|
|||||||
@@ -598,11 +598,7 @@ export async function getSessionMessagesFromDb(sessionId: string): Promise<{
|
|||||||
`).get(sessionId) as Record<string, unknown> | undefined
|
`).get(sessionId) as Record<string, unknown> | undefined
|
||||||
|
|
||||||
const messageRows = db.prepare(`
|
const messageRows = db.prepare(`
|
||||||
SELECT
|
SELECT * FROM messages
|
||||||
id, session_id, role, content, tool_call_id, tool_calls, tool_name,
|
|
||||||
timestamp, token_count, finish_reason, reasoning, reasoning_details,
|
|
||||||
codex_reasoning_items, reasoning_content
|
|
||||||
FROM messages
|
|
||||||
WHERE session_id = ?
|
WHERE session_id = ?
|
||||||
ORDER BY timestamp, id
|
ORDER BY timestamp, id
|
||||||
`).all(sessionId) as Record<string, unknown>[]
|
`).all(sessionId) as Record<string, unknown>[]
|
||||||
@@ -629,22 +625,7 @@ export async function getSessionDetailFromDb(sessionId: string): Promise<HermesS
|
|||||||
const ids = chain.map(session => session.id)
|
const ids = chain.map(session => session.id)
|
||||||
const placeholders = ids.map(() => '?').join(', ')
|
const placeholders = ids.map(() => '?').join(', ')
|
||||||
const messageRows = db.prepare(`
|
const messageRows = db.prepare(`
|
||||||
SELECT
|
SELECT * FROM messages
|
||||||
id,
|
|
||||||
session_id,
|
|
||||||
role,
|
|
||||||
content,
|
|
||||||
tool_call_id,
|
|
||||||
tool_calls,
|
|
||||||
tool_name,
|
|
||||||
timestamp,
|
|
||||||
token_count,
|
|
||||||
finish_reason,
|
|
||||||
reasoning,
|
|
||||||
reasoning_details,
|
|
||||||
codex_reasoning_items,
|
|
||||||
reasoning_content
|
|
||||||
FROM messages
|
|
||||||
WHERE session_id IN (${placeholders})
|
WHERE session_id IN (${placeholders})
|
||||||
ORDER BY timestamp, id
|
ORDER BY timestamp, id
|
||||||
`).all(...ids) as Record<string, unknown>[]
|
`).all(...ids) as Record<string, unknown>[]
|
||||||
@@ -670,22 +651,7 @@ export async function getSessionDetailFromDbWithProfile(sessionId: string, profi
|
|||||||
const ids = chain.map(session => session.id)
|
const ids = chain.map(session => session.id)
|
||||||
const placeholders = ids.map(() => '?').join(', ')
|
const placeholders = ids.map(() => '?').join(', ')
|
||||||
const messageRows = db.prepare(`
|
const messageRows = db.prepare(`
|
||||||
SELECT
|
SELECT * FROM messages
|
||||||
id,
|
|
||||||
session_id,
|
|
||||||
role,
|
|
||||||
content,
|
|
||||||
tool_call_id,
|
|
||||||
tool_calls,
|
|
||||||
tool_name,
|
|
||||||
timestamp,
|
|
||||||
token_count,
|
|
||||||
finish_reason,
|
|
||||||
reasoning,
|
|
||||||
reasoning_details,
|
|
||||||
codex_reasoning_items,
|
|
||||||
reasoning_content
|
|
||||||
FROM messages
|
|
||||||
WHERE session_id IN (${placeholders})
|
WHERE session_id IN (${placeholders})
|
||||||
ORDER BY timestamp, id
|
ORDER BY timestamp, id
|
||||||
`).all(...ids) as Record<string, unknown>[]
|
`).all(...ids) as Record<string, unknown>[]
|
||||||
@@ -706,22 +672,7 @@ export async function getExactSessionDetailFromDbWithProfile(sessionId: string,
|
|||||||
if (!requested) return null
|
if (!requested) return null
|
||||||
|
|
||||||
const messageRows = db.prepare(`
|
const messageRows = db.prepare(`
|
||||||
SELECT
|
SELECT * FROM messages
|
||||||
id,
|
|
||||||
session_id,
|
|
||||||
role,
|
|
||||||
content,
|
|
||||||
tool_call_id,
|
|
||||||
tool_calls,
|
|
||||||
tool_name,
|
|
||||||
timestamp,
|
|
||||||
token_count,
|
|
||||||
finish_reason,
|
|
||||||
reasoning,
|
|
||||||
reasoning_details,
|
|
||||||
codex_reasoning_items,
|
|
||||||
reasoning_content
|
|
||||||
FROM messages
|
|
||||||
WHERE session_id = ?
|
WHERE session_id = ?
|
||||||
ORDER BY timestamp, id
|
ORDER BY timestamp, id
|
||||||
`).all(sessionId) as Record<string, unknown>[]
|
`).all(sessionId) as Record<string, unknown>[]
|
||||||
|
|||||||
@@ -1594,7 +1594,7 @@ export class ChatRunSocket {
|
|||||||
this.enqueueEphemeralDelete(hermesSessionId, profile)
|
this.enqueueEphemeralDelete(hermesSessionId, profile)
|
||||||
return true
|
return true
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
logger.warn(err, '[chat-run-socket] syncFromHermes failed for session %s (hermesId: %s, profile: %s)', localSessionId, hermesSessionId, profile || 'default')
|
logger.warn(err, '[chat-run-socket] syncFromHermes failed for session %s (hermesId: %s, profile: %s): %s', localSessionId, hermesSessionId, profile || 'default', err?.message)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ ${memberSection}
|
|||||||
|
|
||||||
规则:
|
规则:
|
||||||
- 有人用 @${params.agentName} 提及你时才需要回复,重点回应提及你的人。
|
- 有人用 @${params.agentName} 提及你时才需要回复,重点回应提及你的人。
|
||||||
|
- 禁止@自己。
|
||||||
- 回答简洁、对群聊有帮助。
|
- 回答简洁、对群聊有帮助。
|
||||||
- 不要假装是人类,需要时明确表明自己是 AI。
|
- 不要假装是人类,需要时明确表明自己是 AI。
|
||||||
- 对话历史中包含多个人的消息,每条消息前标有发送者名字。
|
- 对话历史中包含多个人的消息,每条消息前标有发送者名字。
|
||||||
|
|||||||
@@ -163,7 +163,9 @@ export class GatewayManager {
|
|||||||
*/
|
*/
|
||||||
private readProfilePort(name: string): { port: number; host: string } {
|
private readProfilePort(name: string): { port: number; host: string } {
|
||||||
const configPath = join(this.profileDir(name), 'config.yaml')
|
const configPath = join(this.profileDir(name), 'config.yaml')
|
||||||
if (!existsSync(configPath)) return { port: 8642, host: '127.0.0.1' }
|
const defaultHost = initSystem === 'container' ? 'hermes-agent' : '127.0.0.1'
|
||||||
|
|
||||||
|
if (!existsSync(configPath)) return { port: 8642, host: defaultHost }
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const content = readFileSync(configPath, 'utf-8')
|
const content = readFileSync(configPath, 'utf-8')
|
||||||
@@ -172,11 +174,11 @@ export class GatewayManager {
|
|||||||
const extra = cfg?.platforms?.api_server?.extra
|
const extra = cfg?.platforms?.api_server?.extra
|
||||||
const rawPort = extra?.port || 8642
|
const rawPort = extra?.port || 8642
|
||||||
const port = typeof rawPort === 'number' ? rawPort : parseInt(rawPort, 10) || 8642
|
const port = typeof rawPort === 'number' ? rawPort : parseInt(rawPort, 10) || 8642
|
||||||
const host = extra?.host || '127.0.0.1'
|
const host = extra?.host || defaultHost
|
||||||
// 端口超出合法范围时回退到默认值
|
// 端口超出合法范围时回退到默认值
|
||||||
return { port: port > 0 && port <= 65535 ? port : 8642, host }
|
return { port: port > 0 && port <= 65535 ? port : 8642, host }
|
||||||
} catch {
|
} catch {
|
||||||
return { port: 8642, host: '127.0.0.1' }
|
return { port: 8642, host: defaultHost }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user