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,5 +1,5 @@
|
||||
import { io, type Socket } from 'socket.io-client'
|
||||
import { request, getBaseUrlValue, getApiKey } from '../client'
|
||||
import { getBaseUrlValue, getApiKey } from '../client'
|
||||
|
||||
export type ContentBlock =
|
||||
| { type: 'text'; text: string }
|
||||
@@ -616,7 +616,3 @@ export function startRunViaSocket(
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchModels(): Promise<{ data: Array<{ id: string }> }> {
|
||||
return request('/api/hermes/v1/models')
|
||||
}
|
||||
|
||||
@@ -72,10 +72,11 @@ export async function fetchConfig(sections?: string[]): Promise<AppConfig> {
|
||||
export async function updateConfigSection(
|
||||
section: string,
|
||||
values: Record<string, any>,
|
||||
options?: { restart?: boolean },
|
||||
): Promise<void> {
|
||||
await request('/api/hermes/config', {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({ section, values }),
|
||||
body: JSON.stringify({ section, values, ...options }),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
import { request } from '../client'
|
||||
|
||||
export interface GatewayStatus {
|
||||
profile: string
|
||||
port: number
|
||||
host: string
|
||||
url: string
|
||||
running: boolean
|
||||
pid?: number
|
||||
diagnostics?: {
|
||||
pid_path: string
|
||||
config_path: string
|
||||
pid_file_exists: boolean
|
||||
config_exists: boolean
|
||||
health_url: string
|
||||
health_checked_at: string
|
||||
health_ok?: boolean
|
||||
reason: string
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchGateways(): Promise<GatewayStatus[]> {
|
||||
const res = await request<{ gateways: GatewayStatus[] }>('/api/hermes/gateways')
|
||||
return res.gateways
|
||||
}
|
||||
|
||||
export async function startGateway(name: string): Promise<GatewayStatus> {
|
||||
const res = await request<{ success: boolean; gateway: GatewayStatus }>(`/api/hermes/gateways/${name}/start`, { method: 'POST' })
|
||||
return res.gateway
|
||||
}
|
||||
|
||||
export async function stopGateway(name: string): Promise<void> {
|
||||
await request(`/api/hermes/gateways/${name}/stop`, { method: 'POST' })
|
||||
}
|
||||
|
||||
export async function checkGatewayHealth(name: string): Promise<GatewayStatus> {
|
||||
const res = await request<{ gateway: GatewayStatus }>(`/api/hermes/gateways/${name}/health`)
|
||||
return res.gateway
|
||||
}
|
||||
@@ -30,6 +30,22 @@ export interface ChatMessage {
|
||||
senderName: string
|
||||
content: string
|
||||
timestamp: number
|
||||
role?: string
|
||||
tool_call_id?: string | null
|
||||
tool_calls?: any[] | null
|
||||
tool_name?: string | null
|
||||
finish_reason?: string | null
|
||||
reasoning?: string | null
|
||||
reasoning_details?: string | null
|
||||
reasoning_content?: string | null
|
||||
isStreaming?: boolean
|
||||
toolName?: string
|
||||
toolCallId?: string
|
||||
toolArgs?: string
|
||||
toolPreview?: string
|
||||
toolResult?: string
|
||||
toolStatus?: 'running' | 'done' | 'error'
|
||||
attachments?: Array<{ id: string; name: string; type: string; size: number; url: string }>
|
||||
}
|
||||
|
||||
export interface MemberInfo {
|
||||
|
||||
@@ -4,7 +4,6 @@ export interface HermesProfile {
|
||||
name: string
|
||||
active: boolean
|
||||
model: string
|
||||
gateway: string
|
||||
alias: string
|
||||
}
|
||||
|
||||
@@ -13,7 +12,6 @@ export interface HermesProfileDetail {
|
||||
path: string
|
||||
model: string
|
||||
provider: string
|
||||
gateway: string
|
||||
skills: number
|
||||
hasEnv: boolean
|
||||
hasSoulMd: boolean
|
||||
|
||||
@@ -2,6 +2,7 @@ import { request, getApiKey, getBaseUrlValue } from '../client'
|
||||
|
||||
export interface SessionSummary {
|
||||
id: string
|
||||
profile?: string
|
||||
source: string
|
||||
model: string
|
||||
provider?: string
|
||||
@@ -48,10 +49,11 @@ export interface HermesMessage {
|
||||
reasoning: string | null
|
||||
}
|
||||
|
||||
export async function fetchSessions(source?: string, limit?: number): Promise<SessionSummary[]> {
|
||||
export async function fetchSessions(source?: string, limit?: number, profile?: string): Promise<SessionSummary[]> {
|
||||
const params = new URLSearchParams()
|
||||
if (source) params.set('source', source)
|
||||
if (limit) params.set('limit', String(limit))
|
||||
if (profile) params.set('profile', profile)
|
||||
const query = params.toString()
|
||||
const res = await request<{ sessions: SessionSummary[] }>(`/api/hermes/sessions${query ? `?${query}` : ''}`)
|
||||
return res.sessions
|
||||
@@ -231,9 +233,11 @@ export async function fetchSessionUsageSingle(id: string): Promise<{ input_token
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchContextLength(profile?: string): Promise<number> {
|
||||
export async function fetchContextLength(profile?: string, provider?: string, model?: string): Promise<number> {
|
||||
const params = new URLSearchParams()
|
||||
if (profile) params.set('profile', profile)
|
||||
if (provider) params.set('provider', provider)
|
||||
if (model) params.set('model', model)
|
||||
const query = params.toString()
|
||||
const res = await request<{ context_length: number }>(`/api/hermes/sessions/context-length${query ? `?${query}` : ''}`)
|
||||
return res.context_length
|
||||
|
||||
@@ -45,11 +45,19 @@ export interface AvailableModelGroup {
|
||||
model_meta?: Record<string, { preview?: boolean; disabled?: boolean; alias?: string }>
|
||||
}
|
||||
|
||||
export interface ProfileAvailableModels {
|
||||
profile: string
|
||||
default: string
|
||||
default_provider: string
|
||||
groups: AvailableModelGroup[]
|
||||
}
|
||||
|
||||
export interface AvailableModelsResponse {
|
||||
default: string
|
||||
default_provider: string
|
||||
groups: AvailableModelGroup[]
|
||||
allProviders: AvailableModelGroup[]
|
||||
profiles?: ProfileAvailableModels[]
|
||||
/** Web UI-only display aliases keyed by provider -> canonical model ID. */
|
||||
model_aliases?: Record<string, Record<string, string>>
|
||||
model_visibility?: ModelVisibility
|
||||
@@ -76,8 +84,18 @@ export async function fetchConfigModels(): Promise<ConfigModelsResponse> {
|
||||
return request<ConfigModelsResponse>('/api/hermes/config/models')
|
||||
}
|
||||
|
||||
export async function fetchAvailableModels(): Promise<AvailableModelsResponse> {
|
||||
return request<AvailableModelsResponse>('/api/hermes/available-models')
|
||||
function currentProfileName(): string {
|
||||
try {
|
||||
return localStorage.getItem('hermes_active_profile_name') || 'default'
|
||||
} catch {
|
||||
return 'default'
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchAvailableModels(profile = currentProfileName()): Promise<AvailableModelsResponse> {
|
||||
const params = new URLSearchParams()
|
||||
params.set('profile', profile || 'default')
|
||||
return request<AvailableModelsResponse>(`/api/hermes/available-models?${params.toString()}`)
|
||||
}
|
||||
|
||||
export async function fetchProviderModels(data: {
|
||||
|
||||
Reference in New Issue
Block a user