Fix bridge history, profile models, and Windows gateway handling (#845)
* feat: support profile-aware group chat bridge flows * feat: route cron jobs through hermes cli * Fix group chat routing and isolate bridge tests * Add Grok image-to-video media skill * Default Grok videos to media directory * Fix bridge profile fallback and cron repeat clearing * Refine bridge chat and gateway platform handling * Filter bridge tool-call text deltas * Preserve structured bridge chat history * Prepare beta release build artifacts * Fix Windows run profile resolution * Fix Windows path compatibility checks * Fix profile-scoped model page display * Hide Windows subprocess windows for jobs and updates * Hide Windows file backend subprocess windows * Avoid Windows gateway restart lock conflicts * Treat Windows gateway lock as running on startup * Force release Windows gateway lock on restart * Tighten Windows gateway lock cleanup * Update chat e2e source expectation * Bump package version to 0.5.30 --------- Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { join } from 'path'
|
||||
import { getActiveProfileDir } from '../../services/hermes/hermes-profile'
|
||||
import type {
|
||||
ConversationDetail,
|
||||
@@ -62,7 +63,7 @@ interface ConversationSessionRow {
|
||||
}
|
||||
|
||||
function conversationDbPath(): string {
|
||||
return `${getActiveProfileDir()}/state.db`
|
||||
return join(getActiveProfileDir(), 'state.db')
|
||||
}
|
||||
|
||||
function normalizeNumber(value: unknown, fallback = 0): number {
|
||||
|
||||
@@ -118,6 +118,7 @@ export const GC_ROOMS_SCHEMA: Record<string, string> = {
|
||||
maxHistoryTokens: 'INTEGER NOT NULL DEFAULT 32000',
|
||||
tailMessageCount: 'INTEGER NOT NULL DEFAULT 10',
|
||||
totalTokens: 'INTEGER NOT NULL DEFAULT 0',
|
||||
sessionSeed: "TEXT NOT NULL DEFAULT '0'",
|
||||
}
|
||||
|
||||
export const GC_MESSAGES_TABLE = 'gc_messages'
|
||||
@@ -129,6 +130,14 @@ export const GC_MESSAGES_SCHEMA: Record<string, string> = {
|
||||
senderName: 'TEXT NOT NULL',
|
||||
content: 'TEXT NOT NULL',
|
||||
timestamp: 'INTEGER NOT NULL',
|
||||
role: "TEXT NOT NULL DEFAULT 'user'",
|
||||
tool_call_id: 'TEXT',
|
||||
tool_calls: 'TEXT',
|
||||
tool_name: 'TEXT',
|
||||
finish_reason: 'TEXT',
|
||||
reasoning: 'TEXT',
|
||||
reasoning_details: 'TEXT',
|
||||
reasoning_content: 'TEXT',
|
||||
}
|
||||
|
||||
export const GC_ROOM_AGENTS_TABLE = 'gc_room_agents'
|
||||
|
||||
@@ -219,9 +219,10 @@ export function renameSession(id: string, title: string): boolean {
|
||||
return result.changes > 0
|
||||
}
|
||||
|
||||
export function listSessions(profile: string, source?: string, limit = 2000): HermesSessionRow[] {
|
||||
export function listSessions(profile?: string, source?: string, limit = 2000): HermesSessionRow[] {
|
||||
if (!isSqliteAvailable()) return []
|
||||
const db = getDb()!
|
||||
const profileFilter = profile?.trim()
|
||||
|
||||
// Use a subquery to generate preview from first user message if not set
|
||||
const sql = `
|
||||
@@ -239,13 +240,17 @@ export function listSessions(profile: string, source?: string, limit = 2000): He
|
||||
''
|
||||
) AS preview
|
||||
FROM ${SESSIONS_TABLE} s
|
||||
WHERE s.profile = ?
|
||||
WHERE 1 = 1
|
||||
${profileFilter ? 'AND s.profile = ?' : ''}
|
||||
${source ? 'AND s.source = ?' : ''}
|
||||
ORDER BY s.last_active DESC
|
||||
LIMIT ?
|
||||
`
|
||||
|
||||
const params: any[] = [profile]
|
||||
const params: any[] = []
|
||||
if (profileFilter) {
|
||||
params.push(profileFilter)
|
||||
}
|
||||
if (source) {
|
||||
params.push(source)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { getActiveProfileDir, getProfileDir } from '../../services/hermes/hermes-profile'
|
||||
import { join } from 'path'
|
||||
import type { LocalUsageStats } from './usage-store'
|
||||
|
||||
const SQLITE_AVAILABLE = (() => {
|
||||
@@ -66,7 +67,7 @@ interface HermesSessionInternalRow extends HermesSessionRow {
|
||||
}
|
||||
|
||||
function sessionDbPath(): string {
|
||||
return `${getActiveProfileDir()}/state.db`
|
||||
return join(getActiveProfileDir(), 'state.db')
|
||||
}
|
||||
|
||||
function normalizeNumber(value: unknown, fallback = 0): number {
|
||||
@@ -643,7 +644,7 @@ export async function getSessionDetailFromDb(sessionId: string): Promise<HermesS
|
||||
|
||||
export async function getSessionDetailFromDbWithProfile(sessionId: string, profile: string): Promise<HermesSessionDetailRow | null> {
|
||||
const { DatabaseSync } = await import('node:sqlite')
|
||||
const dbPath = `${getProfileDir(profile)}/state.db`
|
||||
const dbPath = join(getProfileDir(profile), 'state.db')
|
||||
const db = new DatabaseSync(dbPath, { open: true, readOnly: true })
|
||||
try {
|
||||
const idx = loadAllSessions(db)
|
||||
@@ -670,7 +671,7 @@ export async function getSessionDetailFromDbWithProfile(sessionId: string, profi
|
||||
|
||||
export async function getExactSessionDetailFromDbWithProfile(sessionId: string, profile: string): Promise<HermesSessionDetailRow | null> {
|
||||
const { DatabaseSync } = await import('node:sqlite')
|
||||
const dbPath = `${getProfileDir(profile)}/state.db`
|
||||
const dbPath = join(getProfileDir(profile), 'state.db')
|
||||
const db = new DatabaseSync(dbPath, { open: true, readOnly: true })
|
||||
try {
|
||||
const idx = loadAllSessions(db)
|
||||
@@ -702,7 +703,7 @@ export async function findLatestExactSessionIdWithProfile(
|
||||
if (!trimmed) return null
|
||||
|
||||
const { DatabaseSync } = await import('node:sqlite')
|
||||
const dbPath = `${getProfileDir(profile)}/state.db`
|
||||
const dbPath = join(getProfileDir(profile), 'state.db')
|
||||
const db = new DatabaseSync(dbPath, { open: true, readOnly: true })
|
||||
const loweredQuery = trimmed.toLowerCase()
|
||||
const likePattern = buildLikePattern(loweredQuery)
|
||||
@@ -1212,7 +1213,7 @@ export async function listSessionSummaries(source?: string, limit = 2000, profil
|
||||
}
|
||||
|
||||
const { DatabaseSync } = await import('node:sqlite')
|
||||
const dbPath = profile ? `${getProfileDir(profile)}/state.db` : sessionDbPath()
|
||||
const dbPath = profile ? join(getProfileDir(profile), 'state.db') : sessionDbPath()
|
||||
const db = new DatabaseSync(dbPath, { open: true, readOnly: true })
|
||||
|
||||
try {
|
||||
@@ -1259,7 +1260,7 @@ export async function searchSessionSummariesWithProfile(
|
||||
if (!trimmed) return []
|
||||
|
||||
const { DatabaseSync } = await import('node:sqlite')
|
||||
const dbPath = `${getProfileDir(profile)}/state.db`
|
||||
const dbPath = join(getProfileDir(profile), 'state.db')
|
||||
const db = new DatabaseSync(dbPath, { open: true, readOnly: true })
|
||||
const normalized = sanitizeFtsQuery(trimmed)
|
||||
const prefixQuery = toPrefixQuery(normalized)
|
||||
|
||||
Reference in New Issue
Block a user