Files
zclaw_openfang/docs/archive/v1-viking-dead-code/lib/viking-server-manager.ts
iven 1cf3f585d3 refactor(store): split gatewayStore into specialized domain stores
Major restructuring:
- Split monolithic gatewayStore into 5 focused stores:
  - connectionStore: WebSocket connection and gateway lifecycle
  - configStore: quickConfig, workspaceInfo, MCP services
  - agentStore: clones, usage stats, agent management
  - handStore: hands, approvals, triggers, hand runs
  - workflowStore: workflows, workflow runs, execution

- Update all components to use new stores with selector pattern
- Remove
2026-03-20 22:14:13 +08:00

232 lines
5.8 KiB
TypeScript

/**
* Viking Server Manager - Local OpenViking Server Management
*
* Manages a local OpenViking server instance for privacy-first deployment.
* All data is stored locally in ~/.openviking/ - nothing is uploaded to remote servers.
*
* Usage:
* const manager = getVikingServerManager();
*
* // Check server status
* const status = await manager.getStatus();
*
* // Start server if not running
* if (!status.running) {
* await manager.start();
* }
*
* // Server is now available at http://127.0.0.1:1933
*/
import { invoke } from '@tauri-apps/api/core';
// === Types ===
export interface VikingServerStatus {
running: boolean;
port: number;
pid?: number;
dataDir?: string;
version?: string;
error?: string;
}
export interface VikingServerConfig {
port?: number;
dataDir?: string;
configFile?: string;
}
// === Default Configuration ===
const DEFAULT_CONFIG: Required<VikingServerConfig> = {
port: 1933,
dataDir: '', // Will use default ~/.openviking/workspace
configFile: '', // Will use default ~/.openviking/ov.conf
};
// === Server Manager Class ===
export class VikingServerManager {
private status: VikingServerStatus | null = null;
private startPromise: Promise<VikingServerStatus> | null = null;
/**
* Get current server status
*/
async getStatus(): Promise<VikingServerStatus> {
try {
this.status = await invoke<VikingServerStatus>('viking_server_status');
return this.status;
} catch (err) {
console.error('[VikingServerManager] Failed to get status:', err);
return {
running: false,
port: DEFAULT_CONFIG.port,
error: err instanceof Error ? err.message : String(err),
};
}
}
/**
* Start local OpenViking server
* If server is already running, returns current status
*/
async start(config?: VikingServerConfig): Promise<VikingServerStatus> {
// Prevent concurrent start attempts
if (this.startPromise) {
return this.startPromise;
}
// Check if already running
const currentStatus = await this.getStatus();
if (currentStatus.running) {
console.log('[VikingServerManager] Server already running on port', currentStatus.port);
return currentStatus;
}
this.startPromise = this.doStart(config);
try {
const result = await this.startPromise;
return result;
} finally {
this.startPromise = null;
}
}
private async doStart(config?: VikingServerConfig): Promise<VikingServerStatus> {
const fullConfig = { ...DEFAULT_CONFIG, ...config };
console.log('[VikingServerManager] Starting local server on port', fullConfig.port);
try {
const status = await invoke<VikingServerStatus>('viking_server_start', {
config: {
port: fullConfig.port,
dataDir: fullConfig.dataDir || undefined,
configFile: fullConfig.configFile || undefined,
},
});
this.status = status;
console.log('[VikingServerManager] Server started:', status);
return status;
} catch (err) {
const errorMsg = err instanceof Error ? err.message : String(err);
console.error('[VikingServerManager] Failed to start server:', errorMsg);
this.status = {
running: false,
port: fullConfig.port,
error: errorMsg,
};
return this.status;
}
}
/**
* Stop local OpenViking server
*/
async stop(): Promise<void> {
console.log('[VikingServerManager] Stopping server');
try {
await invoke('viking_server_stop');
this.status = {
running: false,
port: DEFAULT_CONFIG.port,
};
console.log('[VikingServerManager] Server stopped');
} catch (err) {
console.error('[VikingServerManager] Failed to stop server:', err);
throw err;
}
}
/**
* Restart local OpenViking server
*/
async restart(config?: VikingServerConfig): Promise<VikingServerStatus> {
console.log('[VikingServerManager] Restarting server');
try {
const status = await invoke<VikingServerStatus>('viking_server_restart', {
config: config ? {
port: config.port,
dataDir: config.dataDir,
configFile: config.configFile,
} : undefined,
});
this.status = status;
console.log('[VikingServerManager] Server restarted:', status);
return status;
} catch (err) {
const errorMsg = err instanceof Error ? err.message : String(err);
console.error('[VikingServerManager] Failed to restart server:', errorMsg);
this.status = {
running: false,
port: config?.port || DEFAULT_CONFIG.port,
error: errorMsg,
};
return this.status;
}
}
/**
* Ensure server is running, starting if necessary
* This is the main entry point for ensuring availability
*/
async ensureRunning(config?: VikingServerConfig): Promise<boolean> {
const status = await this.getStatus();
if (status.running) {
return true;
}
const startResult = await this.start(config);
return startResult.running;
}
/**
* Get the server URL for HTTP client connections
*/
getServerUrl(port?: number): string {
const actualPort = port || this.status?.port || DEFAULT_CONFIG.port;
return `http://127.0.0.1:${actualPort}`;
}
/**
* Check if server is available (cached status)
*/
isRunning(): boolean {
return this.status?.running ?? false;
}
/**
* Clear cached status (force refresh on next call)
*/
clearCache(): void {
this.status = null;
}
}
// === Singleton ===
let _instance: VikingServerManager | null = null;
export function getVikingServerManager(): VikingServerManager {
if (!_instance) {
_instance = new VikingServerManager();
}
return _instance;
}
export function resetVikingServerManager(): void {
_instance = null;
}