feat: enhance host API authentication handling and add regression tests

This commit is contained in:
duanshuwen
2026-04-23 19:09:30 +08:00
parent 71bcc3b3c5
commit c9617a3777
10 changed files with 471 additions and 127 deletions

View File

@@ -18,8 +18,6 @@ import { CONFIG_KEYS } from '@runtime/lib/constants';
import { normalizeAgentSessionKey } from '@runtime/lib/models';
import type { ContentBlock, RawMessage } from '@runtime/shared/chat-model';
import type { GatewayEvent, GatewayRpcParams, RuntimeRefreshTopic } from './types';
import * as providerHandlers from './handlers/provider';
import * as skillHandlers from './handlers/skills';
import {
createInitialGatewayDiagnostics,
type GatewayDiagnosticsSnapshot,
@@ -64,6 +62,7 @@ import {
} from './reload-policy';
import { GatewayStateController, type GatewayRuntimeStatus } from './state';
import { connectGatewaySocket, waitForGatewayReady } from './ws-client';
import { dispatchGatewayRpcMethod } from './rpc-dispatch';
type RuntimeChangeBroadcast = {
topics: RuntimeRefreshTopic[];
@@ -1785,88 +1784,16 @@ export class GatewayManager extends EventEmitter {
await this.init();
}
const localDispatch = dispatchGatewayRpcMethod(
method,
params,
(event) => this.broadcast(event),
);
if (localDispatch.handled) {
return localDispatch.result;
}
switch (method) {
case 'chat.send': {
const request = params as GatewayRpcParams['chat.send'];
const sessionKey = normalizeAgentSessionKey(request.sessionKey);
const messageText = extractTextFromRawMessage(request.message);
const response = await this.rpcGateway('chat.send', {
sessionKey,
message: messageText,
deliver: false,
idempotencyKey: request.message.id || randomUUID(),
}, { timeoutMs: 30_000 });
const runId = (
isRecord(response) &&
typeof response.runId === 'string' &&
response.runId.trim()
)
? response.runId
: '';
if (!runId) {
throw new Error('OpenClaw Gateway chat.send did not return a runId');
}
return { runId };
}
case 'chat.history': {
const request = params as GatewayRpcParams['chat.history'];
const response = await this.rpcGateway('chat.history', {
sessionKey: normalizeAgentSessionKey(request.sessionKey),
limit: request.limit ?? 50,
}, { timeoutMs: 15_000 });
if (!isRecord(response) || !Array.isArray(response.messages)) {
return [];
}
return response.messages
.map((message) => normalizeGatewayRawMessage(message))
.filter((message): message is RawMessage => message !== null);
}
case 'chat.abort': {
const request = params as GatewayRpcParams['chat.abort'];
await this.rpcGateway('chat.abort', {
sessionKey: normalizeAgentSessionKey(request.sessionKey),
}, { timeoutMs: 10_000 });
return;
}
case 'session.list': {
const response = await this.rpcGateway('sessions.list', {}, { timeoutMs: 10_000 });
if (!isRecord(response) || !Array.isArray(response.sessions)) {
return [];
}
return response.sessions
.map((session) => (
isRecord(session) && typeof session.key === 'string'
? session.key
: null
))
.filter((sessionKey): sessionKey is string => Boolean(sessionKey));
}
case 'session.delete': {
const request = params as GatewayRpcParams['session.delete'];
if (normalizeAgentSessionKey(request.sessionKey).endsWith(':main')) {
return { success: false };
}
await this.rpcGateway('sessions.delete', {
key: normalizeAgentSessionKey(request.sessionKey),
deleteTranscript: true,
}, { timeoutMs: 15_000 });
return { success: true };
}
case 'provider.list':
return providerHandlers.handleProviderList();
case 'provider.getDefault':
return providerHandlers.handleProviderGetDefault();
case 'skills.status':
return skillHandlers.handleSkillsStatus();
case 'skills.update':
return skillHandlers.handleSkillsUpdate(params);
default:
throw new Error(`Unknown gateway RPC method: ${method}`);
}