mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-10-30 19:32:39 +08:00
Merge pull request #10786 from Kilo-Org/foul-oval
fix(cli): skip background port scans in VS Code
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@kilocode/cli": patch
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Skip inferred background-process port scanning in VS Code sessions to avoid unnecessary Bun subprocess polling.
|
||||
@@ -8,6 +8,7 @@ import { SessionID } from "@/session/schema"
|
||||
import { Shell } from "@/shell/shell"
|
||||
import { NonNegativeInt, PositiveInt, optionalOmitUndefined, withStatics } from "@/util/schema"
|
||||
import { zod, ZodOverride } from "@/util/effect-zod"
|
||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
||||
import * as Log from "@opencode-ai/core/util/log"
|
||||
import { spawn, type ChildProcess } from "child_process"
|
||||
import { Context, Effect, Layer, Schema, Types } from "effect"
|
||||
@@ -172,7 +173,8 @@ export namespace BackgroundProcess {
|
||||
return changed
|
||||
}
|
||||
const fallback = active.info.ready && active.start.ready?.port ? [active.start.ready.port] : []
|
||||
const next = Array.from(new Set([...(await Ports.list(pid)), ...fallback])).toSorted((a, b) => a - b)
|
||||
const ports = Flag.KILO_CLIENT === "cli" ? await Ports.list(pid) : []
|
||||
const next = Array.from(new Set([...ports, ...fallback])).toSorted((a, b) => a - b)
|
||||
if (same(active.info.ports, next)) return false
|
||||
active.info.ports = next
|
||||
active.info.time.updated = Date.now()
|
||||
@@ -209,6 +211,7 @@ export namespace BackgroundProcess {
|
||||
|
||||
function poll(active: Active) {
|
||||
if (active.disposed) return
|
||||
if (Flag.KILO_CLIENT !== "cli") return
|
||||
if (terminal(active.info.status)) return
|
||||
if (active.poll) return
|
||||
active.poll = setTimeout(() => {
|
||||
|
||||
@@ -23,6 +23,14 @@ async function script(dir: string, name: string, source: string) {
|
||||
return `${bin} ${arg}`
|
||||
}
|
||||
|
||||
function port() {
|
||||
const server = Bun.serve({ hostname: "127.0.0.1", port: 0, fetch: () => new Response() })
|
||||
const port = server.port
|
||||
server.stop(true)
|
||||
if (!port) throw new Error("Failed to reserve port")
|
||||
return port
|
||||
}
|
||||
|
||||
function update(sessionID: SessionID) {
|
||||
const state: { off?: () => void; timer?: ReturnType<typeof setTimeout> } = {}
|
||||
const promise = new Promise<BackgroundProcess.Info>((resolve, reject) => {
|
||||
@@ -92,6 +100,119 @@ setInterval(() => {}, 1_000)
|
||||
}),
|
||||
)
|
||||
|
||||
it.instance("reports explicit readiness ports for VS Code clients", () =>
|
||||
Effect.gen(function* () {
|
||||
const test = yield* TestInstance
|
||||
const sessionID = SessionID.descending()
|
||||
const listen = port()
|
||||
const command = yield* Effect.promise(() =>
|
||||
script(
|
||||
test.directory,
|
||||
"vscode-ready-port.mjs",
|
||||
`Bun.serve({ hostname: "127.0.0.1", port: ${listen}, fetch: () => new Response() })
|
||||
`,
|
||||
),
|
||||
)
|
||||
const client = process.env["KILO_CLIENT"]
|
||||
process.env["KILO_CLIENT"] = "vscode"
|
||||
|
||||
try {
|
||||
const info = yield* Effect.promise(() =>
|
||||
BackgroundProcess.start({
|
||||
sessionID,
|
||||
command,
|
||||
cwd: test.directory,
|
||||
ready: { port: listen, timeout: 5_000 },
|
||||
}),
|
||||
)
|
||||
|
||||
expect(info.status).toBe("ready")
|
||||
expect(info.ports).toEqual([listen])
|
||||
} finally {
|
||||
yield* Effect.promise(() => BackgroundProcess.stopSession(sessionID))
|
||||
if (client === undefined) delete process.env["KILO_CLIENT"]
|
||||
else process.env["KILO_CLIENT"] = client
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
||||
it.instance("infers ports for CLI clients", () =>
|
||||
Effect.gen(function* () {
|
||||
const test = yield* TestInstance
|
||||
const sessionID = SessionID.descending()
|
||||
const listen = port()
|
||||
const command = yield* Effect.promise(() =>
|
||||
script(
|
||||
test.directory,
|
||||
"cli-port.mjs",
|
||||
`Bun.serve({ hostname: "127.0.0.1", port: ${listen}, fetch: () => new Response() })
|
||||
`,
|
||||
),
|
||||
)
|
||||
const client = process.env["KILO_CLIENT"]
|
||||
process.env["KILO_CLIENT"] = "cli"
|
||||
|
||||
try {
|
||||
const info = yield* Effect.promise(() =>
|
||||
BackgroundProcess.start({
|
||||
sessionID,
|
||||
command,
|
||||
cwd: test.directory,
|
||||
}),
|
||||
)
|
||||
|
||||
let found = yield* Effect.promise(() => BackgroundProcess.get(info.id))
|
||||
if (process.platform !== "win32") {
|
||||
for (let attempt = 0; attempt < 40 && !found?.ports.includes(listen); attempt++) {
|
||||
yield* Effect.promise(() => Bun.sleep(250))
|
||||
found = yield* Effect.promise(() => BackgroundProcess.get(info.id))
|
||||
}
|
||||
}
|
||||
expect(found?.ports).toEqual(process.platform === "win32" ? [] : [listen])
|
||||
} finally {
|
||||
yield* Effect.promise(() => BackgroundProcess.stopSession(sessionID))
|
||||
if (client === undefined) delete process.env["KILO_CLIENT"]
|
||||
else process.env["KILO_CLIENT"] = client
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
||||
it.instance("does not infer ports for VS Code clients", () =>
|
||||
Effect.gen(function* () {
|
||||
const test = yield* TestInstance
|
||||
const sessionID = SessionID.descending()
|
||||
const listen = port()
|
||||
const command = yield* Effect.promise(() =>
|
||||
script(
|
||||
test.directory,
|
||||
"vscode-port.mjs",
|
||||
`Bun.serve({ hostname: "127.0.0.1", port: ${listen}, fetch: () => new Response() })
|
||||
`,
|
||||
),
|
||||
)
|
||||
const client = process.env["KILO_CLIENT"]
|
||||
process.env["KILO_CLIENT"] = "vscode"
|
||||
|
||||
try {
|
||||
const info = yield* Effect.promise(() =>
|
||||
BackgroundProcess.start({
|
||||
sessionID,
|
||||
command,
|
||||
cwd: test.directory,
|
||||
}),
|
||||
)
|
||||
|
||||
yield* Effect.promise(() => Bun.sleep(2_500))
|
||||
const found = yield* Effect.promise(() => BackgroundProcess.get(info.id))
|
||||
expect(found?.ports).toEqual([])
|
||||
} finally {
|
||||
yield* Effect.promise(() => BackgroundProcess.stopSession(sessionID))
|
||||
if (client === undefined) delete process.env["KILO_CLIENT"]
|
||||
else process.env["KILO_CLIENT"] = client
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
||||
it.instance("publishes output updates from process callbacks", () =>
|
||||
Effect.gen(function* () {
|
||||
const test = yield* TestInstance
|
||||
|
||||
Reference in New Issue
Block a user