fix(kernel,server,tui,inference): generic resource gauge + F-002/F-003/F-004

- generic SystemResourceProbe: owner-agnostic /proc/meminfo system RAM
  overlaid on the vendor GPU probe, wired on both managed and static paths
  so the VRAM/GPU/RAM gauge renders with an external llama-server (was dormant)
- F-002: classify provider 4xx (e.g. llama.cpp 400) as terminal, not retryable
  (except 408/429); stops retrying deterministic request failures to exhaustion
- F-003: FileSystemPromptLoader expands leading ~ / ~/ to user home
- F-004: map InferenceFailedEvent + RetryAttemptedEvent to new
  ServerMessage.InferenceFailed / RetryAttempted, decoded+rendered in tui-go;
  ArtifactContentStoredEvent explicitly mapped to null (internal, no warn)
- tests: tilde expansion, SystemResourceProbe (static/managed/fail-soft)
This commit is contained in:
2026-06-10 11:07:08 +04:00
parent a92b5a3531
commit ee24b7786a
14 changed files with 254 additions and 24 deletions
@@ -133,6 +133,10 @@ private const val STAGE_COMPLETE_TOOL = "stage_complete"
private const val OUTPUT_SUMMARY_LIMIT = 500
private const val REPO_MAP_INJECT_TOP_K = 30
// HTTP statuses that are transient despite being 4xx (F-002 retry classification).
private const val HTTP_TIMEOUT = 408
private const val HTTP_TOO_MANY_REQUESTS = 429
@SuppressWarnings(
"ForbiddenComment",
"UnusedParameter",
@@ -474,7 +478,8 @@ abstract class SessionOrchestrator(
}
return when (inferenceResult) {
is InferenceResult.Cancelled -> StageExecutionResult.Failure("CANCELLED", retryable = false)
is InferenceResult.Failed -> StageExecutionResult.Failure(inferenceResult.reason, retryable = true)
is InferenceResult.Failed ->
StageExecutionResult.Failure(inferenceResult.reason, retryable = isRetryableFailure(inferenceResult.reason))
is InferenceResult.Success -> {
if (isCancelled(sessionId)) return StageExecutionResult.Failure("CANCELLED", retryable = false)
// Capture the LLM-emitted artifact's JSON so transition conditions
@@ -1329,6 +1334,16 @@ abstract class SessionOrchestrator(
}
}
// A provider 4xx client error (e.g. llama.cpp 400 "invalid_request") is a deterministic
// request-construction failure — retrying re-sends the identical bad request and exhausts the
// budget for nothing (F-002). Treat 4xx as terminal, except 408 (timeout) and 429 (rate-limit)
// which are transient. Everything else (network/5xx/unknown) stays retryable.
private fun isRetryableFailure(reason: String): Boolean {
val status = Regex("""returned\s+(\d{3})""").find(reason)?.groupValues?.get(1)?.toIntOrNull()
?: return true
return status !in 400..499 || status == HTTP_TIMEOUT || status == HTTP_TOO_MANY_REQUESTS
}
// --- transition helpers ---
internal fun resolveTransition(