File size: 1,615 Bytes
5710dd0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import { serve } from '@hono/node-server';

import { createApp } from './app';
import { hostForUrl, resolveHost, resolveKimiCodeHome, resolvePort, resolveVisAuthToken } from './config';
import type { WebAsset } from './lib/web-asset';

export interface StartVisServerOptions {
  /** Sessions home. Defaults to env KIMI_CODE_HOME, else ~/.kimi-code. */
  readonly homeDir?: string;
  /** Port; 0 = auto-pick a free port. Defaults to env PORT, else 3001. */
  readonly port?: number;
  readonly host?: string;
  readonly authToken?: string;
  readonly webAsset?: WebAsset;
}

export interface StartedVisServer {
  readonly port: number;
  readonly host: string;
  readonly url: string;
  readonly close: () => Promise<void>;
}

export async function startVisServer(
  opts: StartVisServerOptions = {},
): Promise<StartedVisServer> {
  const host = opts.host ?? resolveHost();
  const authToken = opts.authToken ?? resolveVisAuthToken(host);
  const homeDir = opts.homeDir ?? resolveKimiCodeHome();
  const app = await createApp({ authToken, homeDir, webAsset: opts.webAsset });
  const port = opts.port ?? resolvePort();

  return new Promise<StartedVisServer>((resolveStarted, rejectStarted) => {
    const server = serve({ fetch: app.fetch, hostname: host, port }, (info) => {
      resolveStarted({
        port: info.port,
        host,
        url: `http://${hostForUrl(host)}:${info.port}/`,
        close: () =>
          new Promise<void>((done, fail) => {
            server.close((err?: Error) => (err ? fail(err) : done()));
          }),
      });
    });
    server.once('error', rejectStarted);
  });
}