feat(ui): add browser console served by the daemon
Introduce a minimal operations console reachable on a dedicated UI port (default 8081), kept separate from the OpenAI-compatible API port. - ts_web/ holds the SPA shell (index.html, app.css, vanilla app.js) with sidebar navigation for all views from readme.ui.md and a working Overview page backed by a new /_ui/overview JSON endpoint. - scripts/bundle-ui.ts walks ts_web/ and emits ts_bundled/bundle.ts, a single generated module exporting every asset as base64. Mirrors the @stack.gallery/registry pattern so deno compile binaries embed the entire UI with no external filesystem dependency at runtime. - ts/ui/server.ts (UiServer) serves assets from either the bundled map (default, prod) or directly from ts_web/ on disk (dev). The source is chosen per-config and can be overridden by UI_ASSET_SOURCE=disk|bundle. SPA fallback routes unknown extensionless paths to index.html. - IModelGridConfig.ui block with enabled/port/host/assetSource defaults; config init writes the block, the normalizer fills in defaults on load, and the daemon starts/stops the UI server alongside the API. - deno.json gains a bundle:ui task; compile:all now depends on it so released binaries always contain an up-to-date bundle. dev task sets UI_ASSET_SOURCE=disk for hot edits. - ts_bundled/ is gitignored (generated on build). - test/ui-server.smoke.ts exercises bundle and disk modes end to end (index, app.js, SPA fallback, /_ui/overview, 404).
This commit is contained in:
@@ -9,6 +9,7 @@ import { logger } from './logger.ts';
|
||||
import { TIMING } from './constants.ts';
|
||||
import type { ModelGrid } from './modelgrid.ts';
|
||||
import { ApiServer } from './api/server.ts';
|
||||
import { UiServer } from './ui/server.ts';
|
||||
import type { IModelGridConfig } from './interfaces/config.ts';
|
||||
|
||||
/**
|
||||
@@ -18,6 +19,7 @@ export class Daemon {
|
||||
private modelgrid: ModelGrid;
|
||||
private isRunning: boolean = false;
|
||||
private apiServer?: ApiServer;
|
||||
private uiServer?: UiServer;
|
||||
|
||||
constructor(modelgrid: ModelGrid) {
|
||||
this.modelgrid = modelgrid;
|
||||
@@ -48,6 +50,9 @@ export class Daemon {
|
||||
// Start API server
|
||||
await this.startApiServer(config);
|
||||
|
||||
// Start UI server (runs on its own port, serves the operations console)
|
||||
await this.startUiServer(config);
|
||||
|
||||
// Start containers
|
||||
await this.startContainers();
|
||||
|
||||
@@ -86,6 +91,11 @@ export class Daemon {
|
||||
|
||||
this.isRunning = false;
|
||||
|
||||
// Stop UI server
|
||||
if (this.uiServer) {
|
||||
await this.uiServer.stop();
|
||||
}
|
||||
|
||||
// Stop API server
|
||||
if (this.apiServer) {
|
||||
await this.apiServer.stop();
|
||||
@@ -114,6 +124,26 @@ export class Daemon {
|
||||
await this.apiServer.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the UI server, if enabled.
|
||||
*/
|
||||
private async startUiServer(config: IModelGridConfig): Promise<void> {
|
||||
if (!config.ui.enabled) {
|
||||
logger.dim('UI server disabled in configuration');
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info('Starting UI server...');
|
||||
|
||||
this.uiServer = new UiServer(
|
||||
config.ui,
|
||||
this.modelgrid.getContainerManager(),
|
||||
this.modelgrid.getClusterManager(),
|
||||
);
|
||||
|
||||
await this.uiServer.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start configured containers
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user