refactor(desktop): split kernel_commands/pipeline_commands into modules, add SaaS client libs and gateway modules

Split monolithic kernel_commands.rs (2185 lines) and pipeline_commands.rs (1391 lines)
into focused sub-modules under kernel_commands/ and pipeline_commands/ directories.
Add gateway module (commands, config, io, runtime), health_check, and 15 new
TypeScript client libraries for SaaS relay, auth, admin, telemetry, and kernel
sub-systems (a2a, agent, chat, hands, skills, triggers).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
iven
2026-03-31 11:12:47 +08:00
parent d0ae7d2770
commit f79560a911
71 changed files with 8521 additions and 5997 deletions

View File

@@ -74,6 +74,7 @@ import {
import type { GatewayConfigSnapshot, GatewayModelChoice } from './gateway-config';
import { installApiMethods } from './gateway-api';
import { createLogger } from './logger';
import { GatewayHttpError } from './gateway-errors';
const log = createLogger('GatewayClient');
@@ -712,10 +713,8 @@ export class GatewayClient {
const baseUrl = this.getRestBaseUrl();
const response = await fetch(`${baseUrl}${path}`);
if (!response.ok) {
// For 404 errors, throw with status code so callers can handle gracefully
const error = new Error(`REST API error: ${response.status} ${response.statusText}`);
(error as any).status = response.status;
throw error;
const errorBody = await response.text().catch(() => '');
throw new GatewayHttpError(`HTTP ${response.status}: ${errorBody || response.statusText}`, response.status, errorBody);
}
return response.json();
}
@@ -734,10 +733,7 @@ export class GatewayClient {
if (!response.ok) {
const errorBody = await response.text().catch(() => '');
log.error(`POST ${url} failed: ${response.status} ${response.statusText}`, errorBody);
const error = new Error(`REST API error: ${response.status} ${response.statusText}`);
(error as any).status = response.status;
(error as any).body = errorBody;
throw error;
throw new GatewayHttpError(`HTTP ${response.status}: ${errorBody || response.statusText}`, response.status, errorBody);
}
const result = await response.json();
@@ -932,8 +928,8 @@ export class GatewayClient {
} else {
originalHandler?.call(this.ws!, evt);
}
} catch {
// Ignore parse errors
} catch (e) {
log.debug('Parse error in handshake response handler', { error: e });
}
};
@@ -969,14 +965,14 @@ export class GatewayClient {
const listeners = this.eventListeners.get(event);
if (listeners) {
for (const cb of listeners) {
try { cb(payload); } catch { /* ignore listener errors */ }
try { cb(payload); } catch (e) { log.debug('Event listener error', { error: e }); }
}
}
// Also emit wildcard
const wildcardListeners = this.eventListeners.get('*');
if (wildcardListeners) {
for (const cb of wildcardListeners) {
try { cb({ event, payload }); } catch { /* ignore */ }
try { cb({ event, payload }); } catch (e) { log.debug('Wildcard event listener error', { error: e }); }
}
}
}
@@ -1003,7 +999,7 @@ export class GatewayClient {
this.ws.onclose = null;
this.ws.onerror = null;
if (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING) {
try { this.ws.close(); } catch { /* ignore */ }
try { this.ws.close(); } catch (e) { log.debug('WebSocket close failed during cleanup', { error: e }); }
}
this.ws = null;
}
@@ -1117,9 +1113,9 @@ export class GatewayClient {
this.reconnectTimer = window.setTimeout(async () => {
try {
await this.connect();
} catch {
} catch (e) {
/* close handler will trigger another reconnect */
this.log('warn', `Reconnect attempt ${this.reconnectAttempts} failed`);
this.log('warn', `Reconnect attempt ${this.reconnectAttempts} failed: ${e instanceof Error ? e.message : String(e)}`);
}
}, delay);
}