gateway: add local backend daemon controls to dashboard
This commit is contained in:
@@ -4,6 +4,7 @@ import type { MetricsSnapshot, EventEntry, ActiveRequestInfo } from '../metrics.
|
||||
import type { ServiceInfo } from './services.js';
|
||||
import type { NodeLocation, NodeStatus, NodePushToken } from './node.js';
|
||||
import type { SessionAnalyticsSnapshot } from '../../session/index.js';
|
||||
import type { LocalBackendAction, LocalBackendControlResult, LocalBackendStatus } from './localBackends.js';
|
||||
|
||||
/** Per-session token usage report returned by system.tokenUsage. */
|
||||
export interface TokenUsageEntry {
|
||||
@@ -103,6 +104,20 @@ export interface SystemHandlerDeps {
|
||||
error?: string;
|
||||
fetchedAt: number;
|
||||
}>>;
|
||||
/** Optional callback to retrieve local backend daemon statuses. */
|
||||
getLocalBackends?: () => Promise<LocalBackendStatus[]> | LocalBackendStatus[];
|
||||
/** Optional callback to control local backend daemons. */
|
||||
controlLocalBackend?: (backend: string, action: string) => Promise<LocalBackendControlResult>;
|
||||
}
|
||||
|
||||
function normalizeErrorMessage(error: unknown): string {
|
||||
if (error instanceof Error && error.message.trim().length > 0) {
|
||||
return error.message;
|
||||
}
|
||||
if (typeof error === 'string' && error.trim().length > 0) {
|
||||
return error;
|
||||
}
|
||||
return 'Unknown error';
|
||||
}
|
||||
|
||||
export function createSystemHandlers(deps: SystemHandlerDeps) {
|
||||
@@ -285,5 +300,40 @@ export function createSystemHandlers(deps: SystemHandlerDeps) {
|
||||
});
|
||||
return makeResponse(request.id, { providers });
|
||||
},
|
||||
|
||||
'system.localBackends': async (request: GatewayRequest): Promise<OutboundMessage> => {
|
||||
if (!deps.getLocalBackends) {
|
||||
return makeResponse(request.id, { backends: [] });
|
||||
}
|
||||
try {
|
||||
const backends = await deps.getLocalBackends();
|
||||
return makeResponse(request.id, { backends });
|
||||
} catch (error) {
|
||||
return makeError(request.id, ErrorCode.InternalError, `Failed to load local backends: ${normalizeErrorMessage(error)}`);
|
||||
}
|
||||
},
|
||||
|
||||
'system.localBackendControl': async (request: GatewayRequest): Promise<OutboundMessage> => {
|
||||
if (!deps.controlLocalBackend) {
|
||||
return makeError(request.id, ErrorCode.InternalError, 'Local backend control is not available in this environment');
|
||||
}
|
||||
const params = request.params as { backend?: string; action?: LocalBackendAction } | undefined;
|
||||
if (!params?.backend || typeof params.backend !== 'string') {
|
||||
return makeError(request.id, ErrorCode.InvalidRequest, 'backend is required');
|
||||
}
|
||||
if (!params?.action || typeof params.action !== 'string') {
|
||||
return makeError(request.id, ErrorCode.InvalidRequest, 'action is required');
|
||||
}
|
||||
if (!['start', 'restart', 'stop'].includes(params.action)) {
|
||||
return makeError(request.id, ErrorCode.InvalidRequest, 'action must be one of: start, restart, stop');
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await deps.controlLocalBackend(params.backend, params.action);
|
||||
return makeResponse(request.id, result);
|
||||
} catch (error) {
|
||||
return makeError(request.id, ErrorCode.InternalError, `Local backend control failed: ${normalizeErrorMessage(error)}`);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user