mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-09-01 15:32:11 +08:00
Merge branch 'main' into feature/am-pr-view
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Surface process exit signals and structured spawn failure details in server startup diagnostics
|
||||
@@ -6,7 +6,7 @@ import { watchFontSizeConfig } from "./kilo-provider/font-size"
|
||||
import { mapSSEEventToWebviewMessage } from "./kilo-provider-utils"
|
||||
import { resolvePanelProjectDirectory } from "./project-directory"
|
||||
import { seedSessionStatuses } from "./session-status"
|
||||
import type { KiloConnectionService } from "./services/cli-backend"
|
||||
import { type KiloConnectionService, ServerStartupError } from "./services/cli-backend"
|
||||
import { MarketplaceService } from "./services/marketplace"
|
||||
import {
|
||||
fetchMarketplaceData,
|
||||
@@ -123,7 +123,15 @@ export class MarketplacePanelProvider implements vscode.Disposable {
|
||||
)
|
||||
this.subscriptions.push(
|
||||
this.connection.onStateChange((state, err) => {
|
||||
this.post({ type: "connectionState", state, ...(err ? { error: err.message } : {}) })
|
||||
this.post({
|
||||
type: "connectionState",
|
||||
state,
|
||||
...(err ? { error: err.message } : {}),
|
||||
...(err instanceof ServerStartupError && {
|
||||
userMessage: err.userMessage,
|
||||
userDetails: err.userDetails,
|
||||
}),
|
||||
})
|
||||
if (state === "connected") void this.sync(false)
|
||||
}),
|
||||
this.connection.onLanguageChanged((locale) => this.post({ type: "languageChanged", locale })),
|
||||
@@ -155,7 +163,15 @@ export class MarketplacePanelProvider implements vscode.Disposable {
|
||||
await this.connection.connect(this.directory())
|
||||
await this.sync(this.statuses.size === 0)
|
||||
} catch (err) {
|
||||
this.post({ type: "connectionState", state: "error", error: err instanceof Error ? err.message : String(err) })
|
||||
this.post({
|
||||
type: "connectionState",
|
||||
state: "error",
|
||||
error: err instanceof Error ? err.message : String(err),
|
||||
...(err instanceof ServerStartupError && {
|
||||
userMessage: err.userMessage,
|
||||
userDetails: err.userDetails,
|
||||
}),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -282,3 +282,25 @@ describe("KiloConnectionService drainPendingPrompts", () => {
|
||||
expect(cleared).toBe(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe("KiloConnectionService server exit handling", () => {
|
||||
test("reports signal name when process is killed by signal", () => {
|
||||
const service = new KiloConnectionService({} as any)
|
||||
let stateErr: Error | undefined
|
||||
service.onStateChange((state, err) => {
|
||||
if (state === "error") stateErr = err
|
||||
})
|
||||
;(service as any).handleServerExit(null, "SIGSEGV")
|
||||
expect(stateErr?.message).toBe("CLI background process exited with signal SIGSEGV. Retry to reconnect.")
|
||||
})
|
||||
|
||||
test("reports exit code when process exits normally with code", () => {
|
||||
const service = new KiloConnectionService({} as any)
|
||||
let stateErr: Error | undefined
|
||||
service.onStateChange((state, err) => {
|
||||
if (state === "error") stateErr = err
|
||||
})
|
||||
;(service as any).handleServerExit(1, null)
|
||||
expect(stateErr?.message).toBe("CLI background process exited with code 1. Retry to reconnect.")
|
||||
})
|
||||
})
|
||||
|
||||
@@ -138,7 +138,7 @@ export class KiloConnectionService {
|
||||
update: async () => undefined,
|
||||
} satisfies Pick<vscode.Memento, "get" | "update">)
|
||||
this.sandboxPreference = new SandboxPreference(state)
|
||||
this.serverManager = new ServerManager(context, (code) => this.handleServerExit(code))
|
||||
this.serverManager = new ServerManager(context, (code, signal) => this.handleServerExit(code, signal))
|
||||
this.active = vscode.window.state.focused
|
||||
this.windowStateDisposable = vscode.window.onDidChangeWindowState((ws) => {
|
||||
this.active = ws.focused
|
||||
@@ -790,13 +790,11 @@ export class KiloConnectionService {
|
||||
this.questionRevision += 1
|
||||
}
|
||||
|
||||
private handleServerExit(code: number | null): void {
|
||||
console.warn("[Kilo New] ConnectionService: CLI background process exited:", code)
|
||||
private handleServerExit(code: number | null, signal: NodeJS.Signals | null): void {
|
||||
const reason = signal ? `signal ${signal}` : `code ${code ?? "unknown"}`
|
||||
console.warn(`[Kilo New] ConnectionService: CLI background process exited with ${reason}`)
|
||||
this.resetConnection()
|
||||
this.setState(
|
||||
"error",
|
||||
new Error(`CLI background process exited with code ${code ?? "unknown"}. Retry to reconnect.`),
|
||||
)
|
||||
this.setState("error", new Error(`CLI background process exited with ${reason}. Retry to reconnect.`))
|
||||
}
|
||||
|
||||
private async doConnect(workspaceDir: string): Promise<void> {
|
||||
|
||||
+4
-2
@@ -1,6 +1,8 @@
|
||||
export const dict = {
|
||||
"server.processExited": "انتهت عملية CLI بالرمز {{code}} قبل بدء الخادم",
|
||||
"server.startupTimeout": "انتهت مهلة بدء تشغيل الخادم بعد {{seconds}} ثانية",
|
||||
"server.processExited": "تم إنهاء عملية CLI بالرمز {{code}} قبل بدء الخادم",
|
||||
"server.processSignaled": "تم إنهاء عملية CLI بواسطة الإشارة {{signal}} قبل بدء الخادم",
|
||||
"server.spawnFailed": "فشل في تشغيل الملف الثنائي لـ CLI ({{code}})",
|
||||
"server.startupTimeout": "انتهت مهلة بدء تشغيل الخادم بعد {{seconds}} ثوانٍ",
|
||||
"remote.connected": "Kilo Remote: متصل",
|
||||
"remote.connecting": "Kilo Remote: جارٍ الاتصال\u2026",
|
||||
} as const
|
||||
|
||||
+4
-2
@@ -1,6 +1,8 @@
|
||||
export const dict = {
|
||||
"server.processExited": "O processo da CLI foi encerrado com o código {{code}} antes que o servidor fosse iniciado",
|
||||
"server.startupTimeout": "Tempo limite de inicialização do servidor esgotado após {{seconds}} segundos",
|
||||
"server.processExited": "O processo da CLI foi encerrado com o código {{code}} antes da inicialização do servidor",
|
||||
"server.processSignaled": "O processo da CLI foi finalizado pelo sinal {{signal}} antes da inicialização do servidor",
|
||||
"server.spawnFailed": "Falha ao gerar o binário da CLI ({{code}})",
|
||||
"server.startupTimeout": "Tempo limite de inicialização do servidor atingido após {{seconds}} segundos",
|
||||
"remote.connected": "Kilo Remote: Conectado",
|
||||
"remote.connecting": "Kilo Remote: Conectando\u2026",
|
||||
} as const
|
||||
|
||||
+4
-2
@@ -1,6 +1,8 @@
|
||||
export const dict = {
|
||||
"server.processExited": "CLI proces je izašao sa kodom {{code}} prije nego što se server pokrenuo",
|
||||
"server.startupTimeout": "Vrijeme pokretanja servera je isteklo nakon {{seconds}} sekundi",
|
||||
"server.processExited": "CLI proces je izašao s kodom {{code}} prije nego što je server pokrenut",
|
||||
"server.processSignaled": "CLI proces je prekinut signalom {{signal}} prije pokretanja servera",
|
||||
"server.spawnFailed": "Neuspjelo pokretanje CLI binarne datoteke ({{code}})",
|
||||
"server.startupTimeout": "Isteklo je vrijeme za pokretanje servera nakon {{seconds}} sekundi",
|
||||
"remote.connected": "Kilo Remote: Povezano",
|
||||
"remote.connecting": "Kilo Remote: Povezivanje\u2026",
|
||||
} as const
|
||||
|
||||
+4
-2
@@ -1,6 +1,8 @@
|
||||
export const dict = {
|
||||
"server.processExited": "CLI-processen afsluttede med kode {{code}} før serveren startede",
|
||||
"server.startupTimeout": "Serverens opstartstid udløb efter {{seconds}} sekunder",
|
||||
"server.processExited": "CLI-processen afsluttedes med kode {{code}}, før serveren startede",
|
||||
"server.processSignaled": "CLI-processen blev afbrudt af signal {{signal}}, før serveren startede",
|
||||
"server.spawnFailed": "Kunne ikke starte CLI-binærfil ({{code}})",
|
||||
"server.startupTimeout": "Timeout for serverstart efter {{seconds}} sekunder",
|
||||
"remote.connected": "Kilo Remote: Forbundet",
|
||||
"remote.connecting": "Kilo Remote: Forbinder\u2026",
|
||||
} as const
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
export const dict = {
|
||||
"server.processExited": "Der CLI-Prozess wurde mit dem Code {{code}} beendet, bevor der Server gestartet wurde",
|
||||
"server.processSignaled":
|
||||
"Der CLI-Prozess wurde durch das Signal {{signal}} beendet, bevor der Server gestartet wurde",
|
||||
"server.spawnFailed": "Fehler beim Starten der CLI-Binärdatei ({{code}})",
|
||||
"server.startupTimeout": "Zeitüberschreitung beim Serverstart nach {{seconds}} Sekunden",
|
||||
"remote.connected": "Kilo Remote: Verbunden",
|
||||
"remote.connecting": "Kilo Remote: Verbindung wird hergestellt\u2026",
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
export const dict = {
|
||||
"server.processExited": "CLI process exited with code {{code}} before server started",
|
||||
"server.processSignaled": "CLI process terminated by signal {{signal}} before server started",
|
||||
"server.spawnFailed": "Failed to spawn CLI binary ({{code}})",
|
||||
"server.startupTimeout": "Server startup timeout after {{seconds}} seconds",
|
||||
"remote.connected": "Kilo Remote: Connected",
|
||||
"remote.connecting": "Kilo Remote: Connecting\u2026",
|
||||
|
||||
+4
-2
@@ -1,6 +1,8 @@
|
||||
export const dict = {
|
||||
"server.processExited": "El proceso de la CLI finalizó con el código {{code}} antes de que se iniciara el servidor",
|
||||
"server.startupTimeout": "Tiempo de espera de inicio del servidor agotado después de {{seconds}} segundos",
|
||||
"server.processExited": "El proceso CLI finalizó con el código {{code}} antes de que se iniciara el servidor",
|
||||
"server.processSignaled": "El proceso CLI fue terminado por la señal {{signal}} antes de que se iniciara el servidor",
|
||||
"server.spawnFailed": "Error al generar el binario CLI ({{code}})",
|
||||
"server.startupTimeout": "Tiempo de espera agotado para el inicio del servidor después de {{seconds}} segundos",
|
||||
"remote.connected": "Kilo Remote: Conectado",
|
||||
"remote.connecting": "Kilo Remote: Conectando\u2026",
|
||||
} as const
|
||||
|
||||
+4
-2
@@ -1,6 +1,8 @@
|
||||
export const dict = {
|
||||
"server.processExited": "فرآیند CLI با کد {{code}} قبل از راهاندازی سرور خاتمه یافت",
|
||||
"server.processExited": "فرایند CLI قبل از شروع سرور با کد {{code}} خارج شد",
|
||||
"server.processSignaled": "فرایند CLI با سیگنال {{signal}} قبل از شروع سرور متوقف شد",
|
||||
"server.spawnFailed": "اجرای فایل باینری CLI ناموفق بود ({{code}})",
|
||||
"server.startupTimeout": "زمان راهاندازی سرور پس از {{seconds}} ثانیه به پایان رسید",
|
||||
"remote.connected": "Kilo Remote: متصل شد",
|
||||
"remote.connecting": "Kilo Remote: در حال اتصال…",
|
||||
"remote.connecting": "Kilo Remote: در حال اتصال\u2026",
|
||||
} as const
|
||||
|
||||
+6
-4
@@ -1,6 +1,8 @@
|
||||
export const dict = {
|
||||
"server.processExited": "Le processus CLI s'est terminé avec le code {{code}} avant le démarrage du serveur",
|
||||
"server.startupTimeout": "Délai de démarrage du serveur dépassé après {{seconds}} secondes",
|
||||
"remote.connected": "Kilo Remote\u00a0: Connecté",
|
||||
"remote.connecting": "Kilo Remote\u00a0: Connexion\u2026",
|
||||
"server.processExited": "Le processus CLI a quitté avec le code {{code}} avant le démarrage du serveur",
|
||||
"server.processSignaled": "Le processus CLI a été arrêté par le signal {{signal}} avant le démarrage du serveur",
|
||||
"server.spawnFailed": "Échec du lancement du binaire CLI ({{code}})",
|
||||
"server.startupTimeout": "Délai d'attente du démarrage du serveur dépassé après {{seconds}} secondes",
|
||||
"remote.connected": "Kilo Remote : Connecté",
|
||||
"remote.connecting": "Kilo Remote : Connexion en cours\u2026",
|
||||
} as const
|
||||
|
||||
+5
-3
@@ -1,6 +1,8 @@
|
||||
export const dict = {
|
||||
"server.processExited": "Il processo CLI è uscito con codice {{code}} prima dell'avvio del server",
|
||||
"server.processExited": "Il processo CLI è terminato con il codice {{code}} prima dell'avvio del server",
|
||||
"server.processSignaled": "Il processo CLI è stato terminato dal segnale {{signal}} prima dell'avvio del server",
|
||||
"server.spawnFailed": "Impossibile avviare il binario CLI ({{code}})",
|
||||
"server.startupTimeout": "Timeout di avvio del server dopo {{seconds}} secondi",
|
||||
"remote.connected": "Kilo Remote: connesso",
|
||||
"remote.connecting": "Kilo Remote: connessione...",
|
||||
"remote.connected": "Kilo Remote: Connesso",
|
||||
"remote.connecting": "Kilo Remote: Connessione in corso\u2026",
|
||||
} as const
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
export const dict = {
|
||||
"server.processExited": "サーバーが起動する前に、CLI プロセスがコード {{code}} で終了しました",
|
||||
"server.processSignaled": "サーバーが起動する前に、CLI プロセスがシグナル {{signal}} で終了しました",
|
||||
"server.spawnFailed": "CLI バイナリの起動に失敗しました ({{code}})",
|
||||
"server.startupTimeout": "サーバーの起動が {{seconds}} 秒後にタイムアウトしました",
|
||||
"remote.connected": "Kilo Remote: 接続済み",
|
||||
"remote.connecting": "Kilo Remote: 接続中\u2026",
|
||||
|
||||
+4
-2
@@ -1,6 +1,8 @@
|
||||
export const dict = {
|
||||
"server.processExited": "서버가 시작되기 전에 CLI 프로세스가 코드 {{code}}로 종료되었습니다",
|
||||
"server.startupTimeout": "{{seconds}}초 후 서버 시작 시간이 초과되었습니다",
|
||||
"server.processExited": "서버가 시작되기 전에 CLI 프로세스가 코드 {{code}}(으)로 종료되었습니다",
|
||||
"server.processSignaled": "서버가 시작되기 전에 CLI 프로세스가 신호 {{signal}}(으)로 종료되었습니다",
|
||||
"server.spawnFailed": "CLI 바이너리를 생성하지 못했습니다 ({{code}})",
|
||||
"server.startupTimeout": "{{seconds}}초 후 서버 시작 시간 초과",
|
||||
"remote.connected": "Kilo Remote: 연결됨",
|
||||
"remote.connecting": "Kilo Remote: 연결 중\u2026",
|
||||
} as const
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
export const dict = {
|
||||
"server.processExited": "CLI-proces is afgesloten met code {{code}} voordat de server is gestart",
|
||||
"server.processSignaled": "CLI-proces is beëindigd door signaal {{signal}} voordat de server is gestart",
|
||||
"server.spawnFailed": "Kan CLI-binair bestand niet starten ({{code}})",
|
||||
"server.startupTimeout": "Time-out bij opstarten van server na {{seconds}} seconden",
|
||||
"remote.connected": "Kilo Remote: Verbonden",
|
||||
"remote.connecting": "Kilo Remote: Verbinden\u2026",
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
export const dict = {
|
||||
"server.processExited": "CLI-prosessen avsluttet med kode {{code}} før serveren startet",
|
||||
"server.processSignaled": "CLI-prosessen ble avsluttet av signal {{signal}} før serveren startet",
|
||||
"server.spawnFailed": "Kunne ikke starte CLI-binærfil ({{code}})",
|
||||
"server.startupTimeout": "Tidsavbrudd for serveroppstart etter {{seconds}} sekunder",
|
||||
"remote.connected": "Kilo Remote: Tilkoblet",
|
||||
"remote.connecting": "Kilo Remote: Kobler til\u2026",
|
||||
|
||||
+3
-1
@@ -1,5 +1,7 @@
|
||||
export const dict = {
|
||||
"server.processExited": "Proces CLI zakończył się z kodem {{code}} przed uruchomieniem serwera",
|
||||
"server.processExited": "Proces CLI zakończył działanie z kodem {{code}} przed uruchomieniem serwera",
|
||||
"server.processSignaled": "Proces CLI został przerwany przez sygnał {{signal}} przed uruchomieniem serwera",
|
||||
"server.spawnFailed": "Nie udało się uruchomić pliku binarnego CLI ({{code}})",
|
||||
"server.startupTimeout": "Przekroczono limit czasu uruchamiania serwera po {{seconds}} sekundach",
|
||||
"remote.connected": "Kilo Remote: Połączono",
|
||||
"remote.connecting": "Kilo Remote: Łączenie\u2026",
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
export const dict = {
|
||||
"server.processExited": "Процесс CLI завершился с кодом {{code}} до запуска сервера",
|
||||
"server.processSignaled": "Процесс CLI был завершен сигналом {{signal}} до запуска сервера",
|
||||
"server.spawnFailed": "Не удалось запустить исполняемый файл CLI ({{code}})",
|
||||
"server.startupTimeout": "Время ожидания запуска сервера истекло через {{seconds}} секунд",
|
||||
"remote.connected": "Kilo Remote: Подключено",
|
||||
"remote.connecting": "Kilo Remote: Подключение\u2026",
|
||||
|
||||
+4
-2
@@ -1,6 +1,8 @@
|
||||
export const dict = {
|
||||
"server.processExited": "กระบวนการ CLI ออกด้วยรหัส {{code}} ก่อนที่เซิร์ฟเวอร์จะเริ่มทำงาน",
|
||||
"server.startupTimeout": "หมดเวลาการเริ่มต้นเซิร์ฟเวอร์หลังจาก {{seconds}} วินาที",
|
||||
"server.processExited": "กระบวนการ CLI ออกด้วยรหัส {{code}} ก่อนที่เซิร์ฟเวอร์จะเริ่มต้น",
|
||||
"server.processSignaled": "กระบวนการ CLI ถูกยุติโดยสัญญาณ {{signal}} ก่อนที่เซิร์ฟเวอร์จะเริ่มต้น",
|
||||
"server.spawnFailed": "ไม่สามารถเริ่มต้นไบนารี CLI ({{code}})",
|
||||
"server.startupTimeout": "หมดเวลาเริ่มต้นเซิร์ฟเวอร์หลังจาก {{seconds}} วินาที",
|
||||
"remote.connected": "Kilo Remote: เชื่อมต่อแล้ว",
|
||||
"remote.connecting": "Kilo Remote: กำลังเชื่อมต่อ\u2026",
|
||||
} as const
|
||||
|
||||
+3
-1
@@ -1,5 +1,7 @@
|
||||
export const dict = {
|
||||
"server.processExited": "CLI işlemi sunucu başlamadan önce {{code}} koduyla çıktı",
|
||||
"server.processExited": "CLI işlemi sunucu başlatılmadan önce {{code}} koduyla çıktı",
|
||||
"server.processSignaled": "CLI işlemi sunucu başlatılmadan önce {{signal}} sinyali ile sonlandırıldı",
|
||||
"server.spawnFailed": "CLI ikili dosyası başlatılamadı ({{code}})",
|
||||
"server.startupTimeout": "{{seconds}} saniye sonra sunucu başlatma zaman aşımı",
|
||||
"remote.connected": "Kilo Remote: Bağlandı",
|
||||
"remote.connecting": "Kilo Remote: Bağlanıyor\u2026",
|
||||
|
||||
+3
-1
@@ -1,6 +1,8 @@
|
||||
export const dict = {
|
||||
"server.processExited": "Процес CLI завершився з кодом {{code}} до запуску сервера",
|
||||
"server.startupTimeout": "Час очікування запуску сервера вичерпано після {{seconds}} секунд",
|
||||
"server.processSignaled": "Процес CLI був завершений сигналом {{signal}} до запуску сервера",
|
||||
"server.spawnFailed": "Не вдалося запустити двійковий файл CLI ({{code}})",
|
||||
"server.startupTimeout": "Час очікування запуску сервера минув через {{seconds}} секунд",
|
||||
"remote.connected": "Kilo Remote: Підключено",
|
||||
"remote.connecting": "Kilo Remote: Підключення\u2026",
|
||||
} as const
|
||||
|
||||
+4
-2
@@ -1,6 +1,8 @@
|
||||
export const dict = {
|
||||
"server.processExited": "在服务器启动之前,CLI 进程已退出,代码为 {{code}}",
|
||||
"server.startupTimeout": "服务器启动在 {{seconds}} 秒后超时",
|
||||
"server.processExited": "CLI 进程在服务器启动前以代码 {{code}} 退出",
|
||||
"server.processSignaled": "CLI 进程在服务器启动前被信号 {{signal}} 终止",
|
||||
"server.spawnFailed": "生成 CLI 二进制文件失败 ({{code}})",
|
||||
"server.startupTimeout": "{{seconds}} 秒后服务器启动超时",
|
||||
"remote.connected": "Kilo Remote: 已连接",
|
||||
"remote.connecting": "Kilo Remote: 正在连接\u2026",
|
||||
} as const
|
||||
|
||||
+4
-2
@@ -1,6 +1,8 @@
|
||||
export const dict = {
|
||||
"server.processExited": "在伺服器啟動之前,CLI 處理程序已退出,代碼為 {{code}}",
|
||||
"server.startupTimeout": "伺服器啟動在 {{seconds}} 秒後逾時",
|
||||
"server.processExited": "CLI 程序在伺服器啟動前以代碼 {{code}} 退出",
|
||||
"server.processSignaled": "CLI 程序在伺服器啟動前被信號 {{signal}} 終止",
|
||||
"server.spawnFailed": "生成 CLI 二進位檔案失敗 ({{code}})",
|
||||
"server.startupTimeout": "{{seconds}} 秒後伺服器啟動逾時",
|
||||
"remote.connected": "Kilo Remote: 已連線",
|
||||
"remote.connecting": "Kilo Remote: 正在連線\u2026",
|
||||
} as const
|
||||
|
||||
@@ -17,7 +17,7 @@ export interface ServerInstance {
|
||||
const STARTUP_TIMEOUT_SECONDS = 30
|
||||
|
||||
type WorkspaceFolderLike = { uri: { fsPath: string } }
|
||||
type ServerExitListener = (code: number | null) => void
|
||||
type ServerExitListener = (code: number | null, signal: NodeJS.Signals | null) => void
|
||||
|
||||
export function resolveServerCwd(folders: readonly WorkspaceFolderLike[] | undefined, storage: string): string {
|
||||
return folders?.[0]?.uri.fsPath ?? storage
|
||||
@@ -182,25 +182,36 @@ export class ServerManager {
|
||||
stderrLines.push(errorOutput)
|
||||
})
|
||||
|
||||
serverProcess.on("error", (error) => {
|
||||
console.error("[Kilo New] ServerManager: ❌ Process error:", error)
|
||||
serverProcess.on("error", (err: NodeJS.ErrnoException) => {
|
||||
console.error("[Kilo New] ServerManager: ❌ Process error:", err)
|
||||
if (!resolved) {
|
||||
reject(error)
|
||||
const spawnErr = err as NodeJS.ErrnoException & { spawnargs?: string[] }
|
||||
const code = err.code || err.name || "UNKNOWN"
|
||||
const header = t("server.spawnFailed", { code })
|
||||
const lines = [
|
||||
`Error: ${err.message}`,
|
||||
...(err.code ? [`Code: ${err.code}`] : []),
|
||||
...(err.errno !== undefined ? [`Errno: ${err.errno}`] : []),
|
||||
...(err.syscall ? [`Syscall: ${err.syscall}`] : []),
|
||||
...(err.path ? [`Path: ${err.path}`] : []),
|
||||
...(Array.isArray(spawnErr.spawnargs) ? [`Spawn args: ${JSON.stringify(spawnErr.spawnargs)}`] : []),
|
||||
]
|
||||
const { userMessage, userDetails } = toErrorMessage(header, [...lines, ...stderrLines], cliPath)
|
||||
reject(new ServerStartupError(userMessage, userDetails))
|
||||
}
|
||||
})
|
||||
|
||||
serverProcess.on("exit", (code) => {
|
||||
console.log("[Kilo New] ServerManager: 🛑 Process exited with code:", code)
|
||||
serverProcess.on("exit", (code, signal) => {
|
||||
console.warn("[Kilo New] ServerManager: 🛑 Process exited:", { code, signal })
|
||||
if (this.instance?.process === serverProcess) {
|
||||
this.instance = null
|
||||
this.onExit?.(code)
|
||||
this.onExit?.(code, signal)
|
||||
}
|
||||
if (!resolved) {
|
||||
const { userMessage, userDetails } = toErrorMessage(
|
||||
t("server.processExited", { code: code ?? "null" }),
|
||||
stderrLines,
|
||||
cliPath,
|
||||
)
|
||||
const msg = signal
|
||||
? t("server.processSignaled", { signal })
|
||||
: t("server.processExited", { code: code ?? "unknown" })
|
||||
const { userMessage, userDetails } = toErrorMessage(msg, stderrLines, cliPath)
|
||||
reject(new ServerStartupError(userMessage, userDetails))
|
||||
}
|
||||
})
|
||||
|
||||
@@ -295,6 +295,34 @@ describe("toErrorMessage", () => {
|
||||
const result = toErrorMessage("startup failed", ["some output"])
|
||||
expect(result.error).toBe("startup failed")
|
||||
})
|
||||
|
||||
it("formats structured spawn error details with syscall, errno, and args", () => {
|
||||
const spawnLines = [
|
||||
"Error: spawn UNKNOWN",
|
||||
"Code: UNKNOWN",
|
||||
"Errno: -86",
|
||||
"Syscall: spawn",
|
||||
"Path: /path/to/bin/kilo",
|
||||
'Spawn args: ["serve","--port","0"]',
|
||||
]
|
||||
const result = toErrorMessage("Failed to spawn CLI binary (UNKNOWN)", spawnLines, "/path/to/bin/kilo")
|
||||
expect(result.userMessage).toBe("spawn UNKNOWN")
|
||||
expect(result.userDetails).toContain("CLI path: /path/to/bin/kilo")
|
||||
expect(result.userDetails).toContain("Failed to spawn CLI binary (UNKNOWN)")
|
||||
expect(result.userDetails).toContain("Syscall: spawn")
|
||||
expect(result.userDetails).toContain("Errno: -86")
|
||||
})
|
||||
|
||||
it("handles signal termination without stderr lines cleanly", () => {
|
||||
const result = toErrorMessage(
|
||||
"CLI process terminated by signal SIGSEGV before server started",
|
||||
[],
|
||||
"/path/to/bin/kilo",
|
||||
)
|
||||
expect(result.userMessage).toBe("CLI process terminated by signal SIGSEGV before server started")
|
||||
expect(result.userDetails).toContain("CLI path: /path/to/bin/kilo")
|
||||
expect(result.userDetails).toContain("CLI process terminated by signal SIGSEGV before server started")
|
||||
})
|
||||
})
|
||||
|
||||
describe("server workspace helpers", () => {
|
||||
|
||||
Reference in New Issue
Block a user