mirror of
https://github.com/mudler/LocalAI.git
synced 2026-11-06 04:23:15 -05:00
fix(chats): show the network switcher and say why execution status is unknown
The Network row of the Tools menu could never show the Off, Registries and All switcher: the host stopped setting `applies` because isolation alone does not prove network-policy enforcement, and nothing else set it. Let the provider report enforcement in its typed execution status (`networkPolicyEnforced`). The host sets `applies` only when that report is true and the status is available and isolated. The Sandbox reports it for the gVisor and KVM backends, whose guests reach the network only through the proxy that asks the host. Providers that do not report it keep the "not enforced" text. When the host cannot read the status, give the unknown state a reason (`unknown_reason`) in the API and the Tools menu: owner unreachable, not reported, stale, invalid, not selected, no answer or reported unknown. Log the class of each failure, rate limited. After a failure that a restart of the add-on owner can cause, let a long turn bind and read again, at most once every five seconds, instead of keeping the first failure for the whole turn. The Sandbox now reports "unavailable" with a reason when it started without settings, and explains a backend it does not know. When the Sandbox document skills are hidden because the Sandbox is not known to be isolated, say so in the skill list, in the turn note and in the `load_skill` error, instead of "This chat has no skills now". Assisted-by: Claude Code:claude-sonnet-5-5 Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
26 files changed
+833
-81
No files matched your search
@@ -17,6 +17,11 @@ type ExecutionStatus struct {
|
||||
Readiness string `json:"readiness"`
|
||||
Isolation string `json:"isolation"`
|
||||
Explanation string `json:"explanation,omitempty"`
|
||||
// NetworkPolicyEnforced is the provider's report that every network
|
||||
// connection of its commands goes through the host's network policy. It is
|
||||
// kept only for an available, isolated provider; the host still decides
|
||||
// whether to rely on it.
|
||||
NetworkPolicyEnforced bool `json:"networkPolicyEnforced,omitempty"`
|
||||
}
|
||||
|
||||
// DecodeExecutionStatus decodes Result.Payload, never the result envelope.
|
||||
@@ -28,7 +33,7 @@ func DecodeExecutionStatus(b []byte) (ExecutionStatus, error) {
|
||||
if !utf8.Valid(b) {
|
||||
return unknown, fmt.Errorf("invalid execution status UTF-8")
|
||||
}
|
||||
fields, err := exactObjectFields(b, MaxExecutionStatusBytes, "readiness", "isolation", "explanation")
|
||||
fields, err := exactObjectFields(b, MaxExecutionStatusBytes, "readiness", "isolation", "explanation", "networkPolicyEnforced")
|
||||
if err != nil {
|
||||
return unknown, err
|
||||
}
|
||||
@@ -48,5 +53,8 @@ func DecodeExecutionStatus(b []byte) (ExecutionStatus, error) {
|
||||
if v.Readiness != "available" {
|
||||
v.Isolation = "unknown"
|
||||
}
|
||||
if v.Readiness != "available" || v.Isolation != "isolated" {
|
||||
v.NetworkPolicyEnforced = false
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
@@ -47,6 +47,24 @@ var _ = Describe("Execution status payload", func() {
|
||||
Entry("direction", `{"readiness":"available","isolation":"host","explanation":"a\u202eb"}`),
|
||||
Entry("oversized payload", strings.Repeat(" ", 2049)+`{}`),
|
||||
)
|
||||
It("reports network-policy enforcement only for an available isolated provider", func() {
|
||||
for raw, want := range map[string]bool{
|
||||
`{"readiness":"available","isolation":"isolated","networkPolicyEnforced":true}`: true,
|
||||
`{"readiness":"available","isolation":"isolated","networkPolicyEnforced":false}`: false,
|
||||
`{"readiness":"available","isolation":"isolated"}`: false,
|
||||
`{"readiness":"available","isolation":"host","networkPolicyEnforced":true}`: false,
|
||||
`{"readiness":"unavailable","isolation":"isolated","networkPolicyEnforced":true}`: false,
|
||||
} {
|
||||
v, err := DecodeExecutionStatus([]byte(raw))
|
||||
Expect(err).NotTo(HaveOccurred(), raw)
|
||||
Expect(v.NetworkPolicyEnforced).To(Equal(want), raw)
|
||||
}
|
||||
})
|
||||
It("refuses a non-boolean enforcement claim", func() {
|
||||
v, err := DecodeExecutionStatus([]byte(`{"readiness":"available","isolation":"isolated","networkPolicyEnforced":"yes"}`))
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(v.NetworkPolicyEnforced).To(BeFalse())
|
||||
})
|
||||
It("bridges validation into the existing pure model boundary", func() {
|
||||
for _, tc := range []struct {
|
||||
raw string
|
||||
|
||||
Reference in new issue
Block a user