refactor: optional daemon mode

This commit is contained in:
Catriel Müller
2026-05-29 19:50:09 -03:00
parent 1c675ab241
commit 623c9275f2
4 changed files with 25 additions and 25 deletions
@@ -9,7 +9,7 @@ export namespace KiloRunDaemon {
}
export async function attach(input: Input) {
const daemon = await DaemonClient.maybe(DaemonClient.options())
const daemon = await DaemonClient.maybe()
if (!daemon) return false
const dir = input.directory ?? Filesystem.resolve(process.cwd())
const client = createKiloClient({ baseUrl: daemon.url, directory: dir, headers: daemon.headers })
@@ -1,5 +1,5 @@
import { UI } from "@/cli/ui"
import { resolveNetworkOptionsNoConfig, type NetworkOptions } from "@/cli/network"
import type { NetworkOptions } from "@/cli/network"
import { errorMessage } from "@/util/error"
import { TuiConfig } from "@/cli/cmd/tui/config/tui"
import { validateSession } from "@/cli/cmd/tui/validate-session"
@@ -45,8 +45,7 @@ async function session(input: Input, daemon: DaemonClient.Connection) {
export namespace KiloTuiThreadDaemon {
export async function attach(input: Input) {
const net = resolveNetworkOptionsNoConfig(input.args)
const daemon = await DaemonClient.maybe(DaemonClient.options(net))
const daemon = await DaemonClient.maybe()
if (!daemon) return false
const prompt = await input.input()
@@ -14,25 +14,14 @@ export namespace DaemonClient {
return !process.env.KILO_NO_DAEMON
}
export function options(input: Partial<Daemon.Options> = {}): Daemon.Options {
return {
hostname: "127.0.0.1",
port: 0,
mdns: false,
mdnsDomain: "kilo.local",
cors: ["http://127.0.0.1:3017", "http://localhost:3017"],
...input,
}
}
export function headers(state: Daemon.State) {
return { Authorization: `Basic ${state.token}` }
}
export async function connect(input: Daemon.Options): Promise<Connection | undefined> {
export async function connect(): Promise<Connection | undefined> {
if (!enabled()) return undefined
const daemon = await Daemon.start(input)
if (!daemon.running || !daemon.state) throw new Error(daemon.reason ?? "Daemon did not start")
const daemon = await Daemon.status()
if (!daemon.running || !daemon.state) return undefined
return {
url: daemon.state.url,
headers: headers(daemon.state),
@@ -40,8 +29,8 @@ export namespace DaemonClient {
}
}
export async function maybe(input: Daemon.Options): Promise<Connection | undefined> {
return await connect(input).catch((err) => {
export async function maybe(): Promise<Connection | undefined> {
return await connect().catch((err) => {
log.warn("daemon unavailable, falling back to embedded server", { err })
return undefined
})
+17 -5
View File
@@ -123,22 +123,34 @@ describe("daemon manager", () => {
expect(restarted.status).toBe(200)
}, 20_000)
test("daemon client honors the escape hatch", async () => {
test("daemon client does not start a daemon while attaching", async () => {
await using tmp = await tmpdir()
process.env.KILO_NO_DAEMON = "1"
dirs(tmp.path)
const daemon = await DaemonClient.connect(opts(tmp.path))
const daemon = await DaemonClient.connect()
expect(daemon).toBeUndefined()
expect((await Daemon.status()).running).toBe(false)
})
test("daemon client honors the escape hatch", async () => {
await using tmp = await tmpdir()
const started = await Daemon.start(opts(tmp.path))
process.env.KILO_NO_DAEMON = "1"
const daemon = await DaemonClient.connect()
expect(daemon).toBeUndefined()
expect((await Daemon.status()).state?.pid).toBe(started.state?.pid)
}, 20_000)
test("daemon client returns authenticated attach settings", async () => {
await using tmp = await tmpdir()
const started = await Daemon.start(opts(tmp.path))
const daemon = await DaemonClient.connect(opts(tmp.path))
const daemon = await DaemonClient.connect()
expect(daemon?.url).toStartWith("http://127.0.0.1:")
expect(daemon?.url).toBe(started.state?.url)
expect(daemon?.headers.Authorization).toBe(`Basic ${daemon?.state.token}`)
}, 20_000)
})