mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-09-24 16:02:55 +08:00
refactor: address the comments
This commit is contained in:
@@ -176,6 +176,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||
// kilocode_change end
|
||||
|
||||
const fullSyncedSessions = new Set<string>()
|
||||
const deleted = new Set<string>() // kilocode_change
|
||||
let syncedWorkspace = project.workspace.current()
|
||||
|
||||
function sessionListQuery(): { scope?: "project"; path?: string } {
|
||||
@@ -197,6 +198,10 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||
event.subscribe((event) => {
|
||||
switch (event.type) {
|
||||
case "server.instance.disposed":
|
||||
// kilocode_change start
|
||||
deleted.clear()
|
||||
setStore("background_process", {})
|
||||
// kilocode_change end
|
||||
void bootstrap()
|
||||
break
|
||||
case "permission.replied": {
|
||||
@@ -372,14 +377,17 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||
break
|
||||
}
|
||||
|
||||
// kilocode_change start
|
||||
case "session.status": {
|
||||
setStore("session_status", event.properties.sessionID, event.properties.status)
|
||||
break
|
||||
}
|
||||
// kilocode_change end
|
||||
|
||||
// kilocode_change start
|
||||
case "background_process.updated": {
|
||||
const info = event.properties.info
|
||||
deleted.delete(info.id)
|
||||
const list = store.background_process[info.sessionID]
|
||||
if (!list) {
|
||||
setStore("background_process", info.sessionID, [info])
|
||||
@@ -401,6 +409,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||
}
|
||||
|
||||
case "background_process.deleted": {
|
||||
deleted.add(event.properties.processID)
|
||||
const list = store.background_process[event.properties.sessionID]
|
||||
if (!list) break
|
||||
const result = Binary.search(list, event.properties.processID, (item) => item.id)
|
||||
@@ -562,6 +571,10 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||
const workspace = project.workspace.current()
|
||||
if (workspace !== syncedWorkspace) {
|
||||
fullSyncedSessions.clear()
|
||||
// kilocode_change start
|
||||
deleted.clear()
|
||||
setStore("background_process", {})
|
||||
// kilocode_change end
|
||||
syncedWorkspace = workspace
|
||||
}
|
||||
const projectPromise = project.sync()
|
||||
@@ -635,9 +648,11 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||
sdk.client.command.list({ workspace }).then((x) => setStore("command", reconcile(x.data ?? []))),
|
||||
sdk.client.lsp.status({ workspace }).then((x) => setStore("lsp", reconcile(x.data ?? []))),
|
||||
sdk.client.mcp.status({ workspace }).then((x) => setStore("mcp", reconcile(x.data ?? {}))),
|
||||
// kilocode_change start
|
||||
sdk.client.experimental.resource
|
||||
.list({ workspace })
|
||||
.then((x) => setStore("mcp_resource", reconcile(x.data ?? {}))),
|
||||
// kilocode_change end
|
||||
sdk.client.formatter.status({ workspace }).then((x) => setStore("formatter", reconcile(x.data!))), // kilocode_change
|
||||
// kilocode_change start
|
||||
sdk.client.network.list().then((x) => {
|
||||
@@ -655,7 +670,22 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
|
||||
next[item.sessionID].push(item)
|
||||
}
|
||||
for (const list of Object.values(next)) list.sort((a, b) => a.id.localeCompare(b.id))
|
||||
setStore("background_process", reconcile(next))
|
||||
setStore(
|
||||
"background_process",
|
||||
produce((draft) => {
|
||||
for (const [sessionID, list] of Object.entries(next)) {
|
||||
const items = new Map((draft[sessionID] ?? []).map((item) => [item.id, item]))
|
||||
for (const item of list) {
|
||||
if (deleted.has(item.id)) continue
|
||||
const prev = items.get(item.id)
|
||||
if (!prev || item.time.updated >= prev.time.updated) items.set(item.id, item)
|
||||
}
|
||||
const value = Array.from(items.values()).toSorted((a, b) => a.id.localeCompare(b.id))
|
||||
if (value.length === 0) delete draft[sessionID]
|
||||
else draft[sessionID] = value
|
||||
}
|
||||
}),
|
||||
)
|
||||
}),
|
||||
// kilocode_change end
|
||||
sdk.client.session.status({ workspace }).then((x) => {
|
||||
|
||||
@@ -291,8 +291,9 @@ export function Session() {
|
||||
}
|
||||
|
||||
function stopProcesses(sessionID: string) {
|
||||
const workspace = project.workspace.current()
|
||||
for (const id of processSessions(sessionID)) {
|
||||
void sdk.client.backgroundProcess.stopSession({ sessionID: id }).catch((err) => {
|
||||
void sdk.client.backgroundProcess.stopSession({ sessionID: id, workspace }).catch((err) => {
|
||||
Log.Default.warn("failed to stop session background processes", { sessionID: id, err })
|
||||
})
|
||||
}
|
||||
|
||||
@@ -362,6 +362,23 @@ export namespace BackgroundProcess {
|
||||
return proc.exitCode !== null || proc.signalCode !== null
|
||||
}
|
||||
|
||||
function code(err: unknown) {
|
||||
if (!err || typeof err !== "object" || !("code" in err)) return
|
||||
const value = (err as { code?: unknown }).code
|
||||
return typeof value === "string" ? value : undefined
|
||||
}
|
||||
|
||||
function group(pid: number) {
|
||||
try {
|
||||
process.kill(-pid, 0)
|
||||
return true
|
||||
} catch (err) {
|
||||
if (code(err) === "ESRCH") return false
|
||||
log.debug("failed to probe process group", { err, pid })
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
function waitExit(proc: ChildProcess, ms: number) {
|
||||
if (stopped(proc)) return Promise.resolve()
|
||||
return new Promise<void>((resolve) => {
|
||||
@@ -398,7 +415,7 @@ export namespace BackgroundProcess {
|
||||
active.proc.kill("SIGTERM")
|
||||
}
|
||||
await waitExit(active.proc, KILL_MS)
|
||||
if (stopped(active.proc)) return
|
||||
if (stopped(active.proc) && !group(pid)) return
|
||||
try {
|
||||
process.kill(-pid, "SIGKILL")
|
||||
} catch (err) {
|
||||
@@ -434,6 +451,9 @@ export namespace BackgroundProcess {
|
||||
const sh = Shell.acceptable()
|
||||
const cwd = path.resolve(state.dir, input.cwd ?? state.dir)
|
||||
const readyPattern = pattern(input.ready?.pattern)
|
||||
if (input.ready?.port && (await connected(input.ready.port))) {
|
||||
throw new Error(`Ready port is already in use: ${input.ready.port}`)
|
||||
}
|
||||
const args = Shell.args(sh, input.command, cwd)
|
||||
const proc = spawn(sh, args, {
|
||||
cwd,
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useKeyboard, useTerminalDimensions } from "@opentui/solid"
|
||||
import { useDialog } from "@tui/ui/dialog"
|
||||
import { DialogSelect, type DialogSelectOption } from "@tui/ui/dialog-select"
|
||||
import { useKeybind } from "@tui/context/keybind"
|
||||
import { useProject } from "@tui/context/project"
|
||||
import { useRoute } from "@tui/context/route"
|
||||
import { useSDK } from "@tui/context/sdk"
|
||||
import { useSync } from "@tui/context/sync"
|
||||
@@ -58,6 +59,7 @@ function ports(item: Info) {
|
||||
}
|
||||
|
||||
function useActions() {
|
||||
const project = useProject()
|
||||
const sdk = useSDK()
|
||||
const toast = useToast()
|
||||
const [busy, setBusy] = createSignal<{ id: string; kind: Kind }>()
|
||||
@@ -67,11 +69,12 @@ function useActions() {
|
||||
if (kind === "stop" && terminal(item.status)) return
|
||||
|
||||
setBusy({ id: item.id, kind })
|
||||
const workspace = project.workspace.current()
|
||||
try {
|
||||
const result =
|
||||
kind === "stop"
|
||||
? await sdk.client.backgroundProcess.stop({ processID: item.id })
|
||||
: await sdk.client.backgroundProcess.restart({ processID: item.id })
|
||||
? await sdk.client.backgroundProcess.stop({ processID: item.id, workspace })
|
||||
: await sdk.client.backgroundProcess.restart({ processID: item.id, workspace })
|
||||
|
||||
if (result.error) {
|
||||
toast.show({
|
||||
|
||||
@@ -70,6 +70,14 @@ function invalid(action: Action, message: string) {
|
||||
}
|
||||
}
|
||||
|
||||
function missing(id: BackgroundProcess.ID) {
|
||||
return {
|
||||
title: "Background process not found",
|
||||
output: `Background process not found: ${id}`,
|
||||
metadata: { processID: id },
|
||||
}
|
||||
}
|
||||
|
||||
function pattern(ready?: BackgroundProcess.Ready) {
|
||||
if (!ready?.pattern) return
|
||||
try {
|
||||
@@ -100,27 +108,24 @@ export const BackgroundProcessTool = Tool.define<typeof Params, Meta, never, "ba
|
||||
if (params.action !== "start") {
|
||||
const id = params.id
|
||||
if (!id) return invalid(params.action, "Missing id")
|
||||
const found = yield* Effect.promise(() => BackgroundProcess.get(id))
|
||||
if (!found || found.sessionID !== ctx.sessionID) return missing(id)
|
||||
if (params.action === "logs") {
|
||||
const logs = yield* Effect.promise(() => BackgroundProcess.logs(id))
|
||||
if (!logs) return missing(id)
|
||||
return {
|
||||
title: `Logs: ${title(found)}`,
|
||||
output: logs.output || "(no output)",
|
||||
metadata: { processID: found.id, status: found.status },
|
||||
}
|
||||
}
|
||||
const info =
|
||||
params.action === "stop"
|
||||
? yield* Effect.promise(() => BackgroundProcess.stop(id))
|
||||
: params.action === "restart"
|
||||
? yield* Effect.promise(() => BackgroundProcess.restart(id))
|
||||
: yield* Effect.promise(() => BackgroundProcess.get(id))
|
||||
if (!info) {
|
||||
return {
|
||||
title: "Background process not found",
|
||||
output: `Background process not found: ${id}`,
|
||||
metadata: { processID: id },
|
||||
}
|
||||
}
|
||||
if (params.action === "logs") {
|
||||
const logs = yield* Effect.promise(() => BackgroundProcess.logs(id))
|
||||
return {
|
||||
title: `Logs: ${title(info)}`,
|
||||
output: logs?.output || "(no output)",
|
||||
metadata: { processID: info.id, status: info.status },
|
||||
}
|
||||
}
|
||||
: found
|
||||
if (!info) return missing(id)
|
||||
return {
|
||||
title: `${params.action}: ${title(info)}`,
|
||||
output: format(info),
|
||||
@@ -128,8 +133,8 @@ export const BackgroundProcessTool = Tool.define<typeof Params, Meta, never, "ba
|
||||
}
|
||||
}
|
||||
|
||||
const command = params.command
|
||||
if (!command?.trim()) return invalid(params.action, "Missing command")
|
||||
const command = params.command?.trim()
|
||||
if (!command) return invalid(params.action, "Missing command")
|
||||
const err = pattern(params.ready)
|
||||
if (err) return invalid(params.action, err)
|
||||
const inst = yield* InstanceState.context
|
||||
|
||||
Reference in New Issue
Block a user