MCPcopy Create free account
hub / github.com/MoonshotAI/kimi-code / ensureDaemon

Function ensureDaemon

apps/kimi-code/src/cli/sub/server/daemon.ts:291–369  ·  view source on GitHub ↗
(options: EnsureDaemonOptions = {})

Source from the content-addressed store, hash-verified

289 * detached process after this returns.
290 */
291export async function ensureDaemon(options: EnsureDaemonOptions = {}): Promise<EnsureDaemonResult> {
292 const host = options.host ?? DEFAULT_SERVER_HOST;
293 const preferred = options.port ?? DEFAULT_SERVER_PORT;
294 const logLevel = options.logLevel ?? DEFAULT_DAEMON_LOG_LEVEL;
295
296 // 1. Reuse an already-live daemon if one holds the lock.
297 const existing = getLiveLock();
298 if (existing) {
299 const origin = serverOrigin(lockConnectHost(existing), existing.port);
300 if (await waitForServerHealthy(origin, REUSE_HEALTH_TIMEOUT_MS)) {
301 return {
302 origin,
303 reused: true,
304 host: existing.host ?? DEFAULT_SERVER_HOST,
305 port: existing.port,
306 };
307 }
308 // Live pid but not responding (wedged or mid-boot failure). Fall through
309 // and spawn: if it is truly wedged our child loses the lock race and we
310 // reconnect below; if it died, stale takeover lets our child claim it.
311 }
312
313 // 2. No reusable daemon — pick a free port and spawn one detached.
314 const port = await resolveDaemonPort(host, preferred);
315 const child = spawnDaemonChild({
316 host,
317 port,
318 logLevel,
319 debugEndpoints: options.debugEndpoints,
320 insecureNoTls: options.insecureNoTls,
321 allowRemoteShutdown: options.allowRemoteShutdown,
322 allowRemoteTerminals: options.allowRemoteTerminals,
323 allowedHosts: options.allowedHosts,
324 idleGraceMs: options.idleGraceMs,
325 });
326
327 // Watch for an early exit so a boot failure (e.g. the non-loopback TLS gate,
328 // a config error, or a lost lock race with no other daemon to fall back to)
329 // surfaces the real error immediately instead of waiting out the full spawn
330 // timeout. The exit code/signal plus a tail of the daemon log is what tells
331 // the operator *why* it failed.
332 let childExit: { code: number | null; signal: NodeJS.Signals | null } | undefined;
333 child.once('exit', (code, signal) => {
334 childExit = { code, signal };
335 });
336 child.once('error', () => {
337 // Spawn failure (ENOENT etc.) is already recorded in the log by
338 // spawnDaemonChild; treat it as an early exit here.
339 childExit = { code: -1, signal: null };
340 });
341
342 // 3. Wait until some live daemon (ours, or a racer that won the lock) is up.
343 const deadline = Date.now() + SPAWN_TIMEOUT_MS;
344 while (Date.now() < deadline) {
345 const live = getLiveLock();
346 if (live) {
347 const origin = serverOrigin(lockConnectHost(live), live.port);
348 if (await isServerHealthy(origin, 500)) {

Callers 3

handleWebCommandFunction · 0.90
startServerBackgroundFunction · 0.90
server.test.tsFile · 0.85

Calls 13

getLiveLockFunction · 0.90
serverOriginFunction · 0.90
waitForServerHealthyFunction · 0.90
isServerHealthyFunction · 0.90
lockConnectHostFunction · 0.85
resolveDaemonPortFunction · 0.85
spawnDaemonChildFunction · 0.85
formatDaemonBootFailureFunction · 0.85
daemonLogPathFunction · 0.85
formatLogTailFunction · 0.85
sleepFunction · 0.70
onceMethod · 0.65

Tested by

no test coverage detected