mirror of
https://github.com/mudler/LocalAI.git
synced 2026-11-07 21:13:27 -05:00
refactor(addons): remove the shims for older add-on data
No release carried add-ons, so nothing reads older add-on data or manifests. Delete the code that did. - Connectors: the kind and the add-on of the Telegram connectors that core once carried are gone (LegacyAddon, KindTelegram, the stored binding normalization, the platform titles). A binding needs a kind, and its add-on is the one that serves the kind. The conversion of the old agent pool lists every connector as dropped instead of making a Telegram binding, and its notes say so. - The library index reads only the id field of an entry, not addonId. - A host control that has a capability block (the network policy) is attached by that block alone, not by a tool that replaces bash. - The Office create tools no longer answer for the argument names of an earlier schema, and the identity file note about old addresses is gone. - The known debt of the provider-name guard drops the entries of the conversion and of the resource listing shim, and its ceiling goes from 13 to 5. Assisted-by: Claude:claude-sonnet-5-5 go test
This commit is contained in:
38 files changed
+104
-303
No files matched your search
@@ -46,7 +46,7 @@ var _ = Describe("the connector capability", func() {
|
||||
kind := func() *ConnectorKind { return &m.Capabilities.Connector.Kinds[0] }
|
||||
BeforeEach(func() { m.API = VersionRange{Min: 2, Max: 2} })
|
||||
|
||||
It("accepts a thread history with the manifest api 2", func() {
|
||||
It("accepts a thread history", func() {
|
||||
kind().History = &ConnectorHistory{Thread: true, MaxMessages: 50}
|
||||
Expect(ValidateManifest(m, host())).To(Succeed())
|
||||
Expect(kind().ServesThreadHistory()).To(BeTrue())
|
||||
|
||||
@@ -36,7 +36,7 @@ var _ = Describe("The credential slot of an add-on", func() {
|
||||
return h
|
||||
}
|
||||
|
||||
It("is valid with API 2, a connector kind and read tools", func() {
|
||||
It("is valid with a connector kind and read tools", func() {
|
||||
Expect(ValidateManifest(manifest(nil), host())).To(Succeed())
|
||||
})
|
||||
It("needs a connector kind to hold the binding", func() {
|
||||
|
||||
@@ -84,8 +84,7 @@ func CommandsTool(defs []ToolDefinition) (ToolDefinition, bool) {
|
||||
// IsolatedSkills lists the skills of an add-on that need its own commands
|
||||
// provider to report isolated execution: the document-slot skills of an
|
||||
// add-on with a commands tool, unless its descriptor says it does not provide
|
||||
// the runtime for documents. A commands tool without a descriptor (a manifest
|
||||
// of API 1) counts as providing it, so such an add-on keeps the check.
|
||||
// the runtime for documents. A commands tool without a descriptor counts as providing it, so such an add-on keeps the check.
|
||||
func IsolatedSkills(defs []ToolDefinition, skills []SkillDefinition) []string {
|
||||
tool, ok := CommandsTool(defs)
|
||||
if !ok {
|
||||
|
||||
@@ -39,9 +39,8 @@ type HostControl struct {
|
||||
// block needs no shadowed tool.
|
||||
Capability string
|
||||
// Shadows is a built-in tool the add-on must replace with a valid tool,
|
||||
// AnyShadow for any, or "" for none. A control with a Capability applies
|
||||
// it only to an add-on that does not declare the block: a manifest
|
||||
// written before the block existed keeps its attachment.
|
||||
// AnyShadow for any, or "" for none. A control with a Capability is not
|
||||
// attached by a shadowed tool: the add-on must declare the block.
|
||||
Shadows string
|
||||
}
|
||||
|
||||
@@ -59,7 +58,7 @@ func declares(c Capabilities, name string) bool {
|
||||
|
||||
// HostControls is the closed registry of host controls.
|
||||
var HostControls = []HostControl{
|
||||
{ID: ControlNetworkPolicy, Grant: "egress.check", Capability: CapabilityNetwork, Shadows: "bash"},
|
||||
{ID: ControlNetworkPolicy, Grant: "egress.check", Capability: CapabilityNetwork},
|
||||
{ID: ControlToolProviders, Shadows: AnyShadow},
|
||||
}
|
||||
|
||||
@@ -115,8 +114,9 @@ func grantCovers(grants []string, op string) bool {
|
||||
// EntitledControls returns the controls of the manifest that the host draws
|
||||
// for it: those declared in ui.controls whose grant is among grants (the
|
||||
// operation prefixes the host setting gives this add-on) and that the add-on
|
||||
// attaches: it declares the control's capability block, or it replaces the
|
||||
// built-in tool the control names with a valid tool. The order of the manifest is
|
||||
// attaches: it declares the control's capability block, or, for a control
|
||||
// without one, it replaces the built-in tool the control names with a valid
|
||||
// tool. The order of the manifest is
|
||||
// kept. A control the add-on is not entitled to is dropped, never an error:
|
||||
// an administrator can remove a grant at any time.
|
||||
func EntitledControls(m Manifest, grants []string) []string {
|
||||
@@ -135,7 +135,10 @@ func EntitledControls(m Manifest, grants []string) []string {
|
||||
continue
|
||||
}
|
||||
switch {
|
||||
case c.Capability != "" && declares(m.Capabilities, c.Capability):
|
||||
case c.Capability != "":
|
||||
if !declares(m.Capabilities, c.Capability) {
|
||||
continue
|
||||
}
|
||||
case c.Shadows == "":
|
||||
case c.Shadows == AnyShadow:
|
||||
if len(shadows) == 0 {
|
||||
|
||||
@@ -4,6 +4,7 @@ package contract
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"slices"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
@@ -16,11 +17,16 @@ var _ = Describe("Host controls", func() {
|
||||
// runner is an add-on that runs commands, with the controls it asks for.
|
||||
// Any ID works: the host never looks at it.
|
||||
runner := func(id string, controls ...string) Manifest {
|
||||
return Manifest{SchemaVersion: 1, ID: id, Version: "1.0.0", Executable: "bin/" + id, OS: "linux", Arch: "amd64",
|
||||
m := Manifest{SchemaVersion: 1, ID: id, Version: "1.0.0", Executable: "bin/" + id, OS: "linux", Arch: "amd64",
|
||||
Host: VersionRange{Min: 1, Max: 1}, API: VersionRange{Min: 2, Max: 2}, Protocol: VersionRange{Min: 1, Max: 1}, DataFormat: VersionRange{Min: 1, Max: 1},
|
||||
Capabilities: Capabilities{Actions: true, Tools: []string{"bash"},
|
||||
ToolDefinitions: []ToolDefinition{{Name: "bash", Description: "Run a command.", Kind: ToolKindAction, InputSchema: json.RawMessage(bashSchema), Shadows: "bash"}},
|
||||
UI: &UI{Entry: "ui/main.js", SDK: VersionRange{Min: 2, Max: 2}, Controls: controls}}}
|
||||
if slices.Contains(controls, ControlNetworkPolicy) {
|
||||
m.Capabilities.Network = &NetworkCapability{Kind: NetworkKindEgressCheck}
|
||||
m.Capabilities.HostOperations = &HostOperations{Optional: []string{"egress.check"}}
|
||||
}
|
||||
return m
|
||||
}
|
||||
host := HostCompatibility{Host: 1, API: 2, Protocol: 1, SDK: HostSDKVersion, DataFormat: 1, OS: "linux", Arch: "amd64"}
|
||||
|
||||
@@ -48,15 +54,15 @@ var _ = Describe("Host controls", func() {
|
||||
Expect(m.Capabilities.UI.Controls).To(Equal([]string{ControlToolProviders}))
|
||||
})
|
||||
|
||||
It("draws the network policy only for an add-on granted egress that runs bash", func() {
|
||||
It("draws the network policy only for an add-on granted egress that declares a network", func() {
|
||||
Expect(EntitledControls(runner("sandbox", ControlNetworkPolicy), []string{"workspace.", "egress."})).To(Equal([]string{ControlNetworkPolicy}))
|
||||
// A narrower grant that still covers the check is enough.
|
||||
Expect(EntitledControls(runner("sandbox", ControlNetworkPolicy), []string{"egress.check"})).To(Equal([]string{ControlNetworkPolicy}))
|
||||
Expect(EntitledControls(runner("sandbox", ControlNetworkPolicy), []string{"workspace."})).To(BeEmpty())
|
||||
Expect(EntitledControls(runner("sandbox", ControlNetworkPolicy), nil)).To(BeEmpty())
|
||||
m := runner("sandbox", ControlNetworkPolicy)
|
||||
m.Capabilities.ToolDefinitions[0].Shadows = ""
|
||||
Expect(EntitledControls(m, []string{"egress."})).To(BeEmpty())
|
||||
m.Capabilities.Network = nil
|
||||
Expect(EntitledControls(m, []string{"egress."})).To(BeEmpty(), "a bash tool alone does not attach the control")
|
||||
})
|
||||
|
||||
It("serves a second add-on with the same controls, by its grant and not by its name", func() {
|
||||
@@ -69,10 +75,11 @@ var _ = Describe("Host controls", func() {
|
||||
It("draws the tool providers for an add-on that replaces any built-in tool", func() {
|
||||
web := runner("web", ControlToolProviders, ControlNetworkPolicy)
|
||||
web.Capabilities.Actions = false
|
||||
web.Capabilities.Network, web.Capabilities.HostOperations = nil, nil
|
||||
web.Capabilities.Tools = []string{"fetch"}
|
||||
web.Capabilities.ToolDefinitions = []ToolDefinition{{Name: "fetch", Description: "Read a page.", Kind: ToolKindRead, InputSchema: json.RawMessage(fetchSchema), Shadows: "web_fetch"}}
|
||||
Expect(ValidateManifest(web, host)).To(Succeed())
|
||||
// The network policy needs bash, even with the grant.
|
||||
// The network policy needs a declared network, even with the grant.
|
||||
Expect(EntitledControls(web, []string{"egress."})).To(Equal([]string{ControlToolProviders}))
|
||||
web.Capabilities.ToolDefinitions[0].Shadows = ""
|
||||
Expect(EntitledControls(web, []string{"egress."})).To(BeEmpty())
|
||||
|
||||
@@ -128,8 +128,7 @@ type Capabilities struct {
|
||||
// (see network.go). It attaches the network-policy host control.
|
||||
Network *NetworkCapability `json:"network,omitempty"`
|
||||
// ContextFiles name small index files of the user's home that the host
|
||||
// loads into the prompt of a chat (see contextfiles.go). They need
|
||||
// manifest API 2.
|
||||
// loads into the prompt of a chat (see contextfiles.go).
|
||||
ContextFiles []ContextFile `json:"contextFiles,omitempty"`
|
||||
|
||||
// Credentials declare the secret that the host keeps for the person and
|
||||
@@ -157,7 +156,7 @@ type ResourceTools struct {
|
||||
// backing data. It is reachable only from the UI-only delete endpoint.
|
||||
Delete string `json:"delete,omitempty"`
|
||||
// List asks the host for a read tool that lists the resources the caller
|
||||
// may use (see ResourceList). It needs manifest API 2.
|
||||
// may use (see ResourceList).
|
||||
List *ResourceList `json:"list,omitempty"`
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
var _ = Describe("The network capability", func() {
|
||||
const bashSchema = `{"type":"object","properties":{"command":{"type":"string"}},"required":["command"],"additionalProperties":false}`
|
||||
|
||||
// withNetwork is a manifest of API 2 that asks for the network-policy
|
||||
// withNetwork is a manifest that asks for the network-policy
|
||||
// control. It runs no command tool unless shadowsBash is set, so what is
|
||||
// drawn can only come from the declared capability.
|
||||
withNetwork := func(n *NetworkCapability, shadowsBash bool) Manifest {
|
||||
@@ -42,7 +42,7 @@ var _ = Describe("The network capability", func() {
|
||||
declared := &NetworkCapability{Kind: NetworkKindEgressCheck, Title: "Runbox network",
|
||||
Presets: []NetworkPreset{{ID: "off", Title: "Closed"}, {ID: "all", Title: "Open"}}}
|
||||
|
||||
It("is valid when the manifest accepts API 2 and lists the egress check", func() {
|
||||
It("is valid when the manifest lists the egress check", func() {
|
||||
Expect(ValidateManifest(withNetwork(declared, false), host())).To(Succeed())
|
||||
})
|
||||
|
||||
@@ -85,10 +85,8 @@ var _ = Describe("The network capability", func() {
|
||||
Expect(EntitledControls(withNetwork(declared, false), []string{"workspace."})).To(BeEmpty())
|
||||
Expect(EntitledControls(withNetwork(declared, true), nil)).To(BeEmpty())
|
||||
})
|
||||
It("is drawn for a manifest that declares no network and replaces bash, as before", func() {
|
||||
Expect(EntitledControls(withNetwork(nil, true), grants)).To(Equal([]string{ControlNetworkPolicy}))
|
||||
})
|
||||
It("is not drawn for a manifest that declares no network and does not replace bash", func() {
|
||||
It("is not drawn for a manifest that declares no network, whether or not it replaces bash", func() {
|
||||
Expect(EntitledControls(withNetwork(nil, true), grants)).To(BeEmpty())
|
||||
Expect(EntitledControls(withNetwork(nil, false), grants)).To(BeEmpty())
|
||||
})
|
||||
It("does not read the add-on ID", func() {
|
||||
@@ -120,11 +118,10 @@ var _ = Describe("The network capability", func() {
|
||||
Expect(m.Capabilities.Network).To(Equal(&NetworkCapability{Kind: NetworkKindEgressCheck, Title: "Sandbox"}))
|
||||
Expect(EntitledControls(m, []string{"egress."})).To(ContainElement(ControlNetworkPolicy))
|
||||
})
|
||||
It("keeps the control through its bash tool when an older manifest declares no network", func() {
|
||||
It("loses the control when it declares no network", func() {
|
||||
m := load()
|
||||
m.Capabilities.Network = nil
|
||||
Expect(EntitledControls(m, []string{"egress."})).To(ContainElement(ControlNetworkPolicy))
|
||||
Expect(EntitledControls(m, nil)).NotTo(ContainElement(ControlNetworkPolicy))
|
||||
Expect(EntitledControls(m, []string{"egress."})).NotTo(ContainElement(ControlNetworkPolicy))
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -32,8 +32,7 @@ type SkillDefinition struct {
|
||||
// add-on skill.
|
||||
Shadows string `json:"shadows,omitempty"`
|
||||
// Slot describes the slot this skill serves: the files it covers and the
|
||||
// words to say about them (see SlotDefinition). It needs Shadows and
|
||||
// manifest API 2. A skill that shadows a default slot may leave it out.
|
||||
// words to say about them (see SlotDefinition). It needs Shadows. A skill that shadows a default slot may leave it out.
|
||||
Slot *SlotDefinition `json:"slot,omitempty"`
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ var defaultSlots = sync.OnceValue(func() []Slot {
|
||||
|
||||
// DefaultSlots are the slots the host knows without any declaration, read
|
||||
// from data. A skill that shadows one of them and declares no slot of its own
|
||||
// (a manifest of API 1) is served by these.
|
||||
// is served by these.
|
||||
func DefaultSlots() []Slot { return slices.Clone(defaultSlots()) }
|
||||
|
||||
// DefaultSlot returns the default slot called name.
|
||||
|
||||
Reference in new issue
Block a user