refactor: restructure project for multi-agent extensibility
- Migrate source to packages/client and packages/server directories - Namespace all Hermes-specific code under hermes/ subdirectories (api/hermes/, components/hermes/, views/hermes/, stores/hermes/) - Add hermes.* route names and /hermes/* path prefixes - Upgrade @koa/router to v15, adapt path-to-regexp v8 syntax - Fix proxy path rewriting: /api/hermes/v1/* → /v1/*, /api/hermes/* → /api/* - Fix frontend API paths to match backend /api/hermes/* routes - Fix WebSocket terminal path to /api/hermes/terminal - Add proxyMiddleware for reliable unmatched route proxying - Add profiles route module and hermes-cli profile commands - Update CLAUDE.md development guide with new architecture - Add Chinese README (README_zh.md) - Add Web Terminal feature to README Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
import { request, getBaseUrlValue, getApiKey } from '../client'
|
||||
|
||||
export interface ChatMessage {
|
||||
role: 'user' | 'assistant' | 'system'
|
||||
content: string
|
||||
}
|
||||
|
||||
export interface StartRunRequest {
|
||||
input: string | ChatMessage[]
|
||||
instructions?: string
|
||||
conversation_history?: ChatMessage[]
|
||||
session_id?: string
|
||||
model?: string
|
||||
}
|
||||
|
||||
export interface StartRunResponse {
|
||||
run_id: string
|
||||
status: string
|
||||
}
|
||||
|
||||
// SSE event types from /v1/runs/{id}/events
|
||||
export interface RunEvent {
|
||||
event: string
|
||||
run_id?: string
|
||||
delta?: string
|
||||
tool?: string
|
||||
name?: string
|
||||
preview?: string
|
||||
timestamp?: number
|
||||
error?: string
|
||||
}
|
||||
|
||||
export async function startRun(body: StartRunRequest): Promise<StartRunResponse> {
|
||||
return request<StartRunResponse>('/api/hermes/v1/runs', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
})
|
||||
}
|
||||
|
||||
export function streamRunEvents(
|
||||
runId: string,
|
||||
onEvent: (event: RunEvent) => void,
|
||||
onDone: () => void,
|
||||
onError: (err: Error) => void,
|
||||
) {
|
||||
const baseUrl = getBaseUrlValue()
|
||||
const token = getApiKey()
|
||||
const url = `${baseUrl}/api/hermes/v1/runs/${runId}/events${token ? `?token=${encodeURIComponent(token)}` : ''}`
|
||||
|
||||
let closed = false
|
||||
const source = new EventSource(url)
|
||||
|
||||
source.onmessage = (e) => {
|
||||
if (closed) return
|
||||
try {
|
||||
const parsed = JSON.parse(e.data)
|
||||
onEvent(parsed)
|
||||
|
||||
if (parsed.event === 'run.completed' || parsed.event === 'run.failed') {
|
||||
closed = true
|
||||
source.close()
|
||||
onDone()
|
||||
}
|
||||
} catch {
|
||||
onEvent({ event: 'message', delta: e.data })
|
||||
}
|
||||
}
|
||||
|
||||
source.onerror = () => {
|
||||
if (closed) return
|
||||
closed = true
|
||||
source.close()
|
||||
onError(new Error('SSE connection error'))
|
||||
}
|
||||
|
||||
// Return AbortController-compatible object
|
||||
return {
|
||||
abort: () => {
|
||||
if (!closed) {
|
||||
closed = true
|
||||
source.close()
|
||||
}
|
||||
},
|
||||
} as unknown as AbortController
|
||||
}
|
||||
|
||||
export async function fetchModels(): Promise<{ data: Array<{ id: string }> }> {
|
||||
return request('/api/hermes/v1/models')
|
||||
}
|
||||
Reference in New Issue
Block a user