mirror of
https://github.com/mudler/LocalAI.git
synced 2026-11-06 12:33:16 -05:00
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>
61 lines
2.2 KiB
Go
61 lines
2.2 KiB
Go
// SPDX-License-Identifier: MIT
|
|
package contract
|
|
|
|
import (
|
|
"fmt"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
const (
|
|
MaxExecutionStatusBytes = 2048
|
|
MaxExecutionExplanationChars = 200
|
|
)
|
|
|
|
// ExecutionStatus is provider-reported observation, not authority or a host
|
|
// isolation guarantee. Only DecodeExecutionStatus validates a wire payload.
|
|
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.
|
|
// Unknown/duplicate/trailing fields (including outputs) are refused. On any
|
|
// error it returns unknown/unknown, not partially trusted provider data.
|
|
func DecodeExecutionStatus(b []byte) (ExecutionStatus, error) {
|
|
unknown := ExecutionStatus{Readiness: "unknown", Isolation: "unknown"}
|
|
var v ExecutionStatus
|
|
if !utf8.Valid(b) {
|
|
return unknown, fmt.Errorf("invalid execution status UTF-8")
|
|
}
|
|
fields, err := exactObjectFields(b, MaxExecutionStatusBytes, "readiness", "isolation", "explanation", "networkPolicyEnforced")
|
|
if err != nil {
|
|
return unknown, err
|
|
}
|
|
if err := strictJSON(b, &v, MaxExecutionStatusBytes); err != nil {
|
|
return unknown, err
|
|
}
|
|
if v.Readiness != "available" && v.Readiness != "unavailable" && v.Readiness != "unknown" {
|
|
return unknown, fmt.Errorf("invalid execution readiness")
|
|
}
|
|
if v.Isolation != "isolated" && v.Isolation != "host" && v.Isolation != "unknown" {
|
|
return unknown, fmt.Errorf("invalid execution isolation")
|
|
}
|
|
// Distinguish absent explanation from explicit null or empty text.
|
|
if _, present := fields["explanation"]; present && !ValidPlainText(v.Explanation, MaxExecutionExplanationChars) {
|
|
return unknown, fmt.Errorf("invalid execution explanation")
|
|
}
|
|
if v.Readiness != "available" {
|
|
v.Isolation = "unknown"
|
|
}
|
|
if v.Readiness != "available" || v.Isolation != "isolated" {
|
|
v.NetworkPolicyEnforced = false
|
|
}
|
|
return v, nil
|
|
}
|