mirror of
https://github.com/mudler/LocalAI.git
synced 2026-11-06 04:23:15 -05:00
feat(addons): declare the connector file operations in Slack and Telegram
The two connectors move files through connector.file.get and connector.file.put but their manifests asked for nothing, so the install dialog and blanket approval could not cover them. Declare both as optional: a connector works without files. Delivery is pull, so neither calls connector.inbound and it is not declared. The audit of official packages now reads the operation constants of the shared connector code. A deployment whose policy file already grants the connector prefix sees no change. Assisted-by: Claude:claude-sonnet-5-5 go
This commit is contained in:
3 files changed
+56
-24
No files matched your search
@@ -10,6 +10,9 @@
|
||||
"protocol": { "min": 1, "max": 1 },
|
||||
"dataFormat": { "min": 1, "max": 1 },
|
||||
"capabilities": {
|
||||
"hostOperations": {
|
||||
"optional": ["connector.file.get", "connector.file.put"]
|
||||
},
|
||||
"connector": {
|
||||
"kinds": [
|
||||
{
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
"protocol": { "min": 1, "max": 1 },
|
||||
"dataFormat": { "min": 1, "max": 1 },
|
||||
"capabilities": {
|
||||
"hostOperations": {
|
||||
"optional": ["connector.file.get", "connector.file.put"]
|
||||
},
|
||||
"connector": {
|
||||
"kinds": [
|
||||
{
|
||||
|
||||
@@ -27,6 +27,19 @@ var officialRequests = map[string]contract.HostOperations{
|
||||
"office": {Required: strings.Fields("workspace.export workspace.import")},
|
||||
"sandbox": {Required: strings.Fields("workspace.changes workspace.commit workspace.materialize"), Optional: strings.Fields("egress.audit egress.check workspace.admin")},
|
||||
"web": {Optional: []string{"workspace.admin"}},
|
||||
// A connector moves files only when the person turns files on, so both
|
||||
// file operations are optional. Delivery is pull, so neither add-on calls
|
||||
// connector.inbound.
|
||||
"slack": {Optional: strings.Fields("connector.file.get connector.file.put")},
|
||||
"telegram": {Optional: strings.Fields("connector.file.get connector.file.put")},
|
||||
}
|
||||
|
||||
// connectorRoot holds the file transfer code that slack and telegram share. It
|
||||
// names its operations by constant, so the audit reads those too.
|
||||
const connectorRoot = "addons/internal/connector"
|
||||
|
||||
var connectorConstants = map[string]string{
|
||||
"ConnectorInboundOp": contract.ConnectorInboundOp, "ConnectorFilePutOp": contract.ConnectorFilePutOp, "ConnectorFileGetOp": contract.ConnectorFileGetOp,
|
||||
}
|
||||
|
||||
var _ = Describe("official typed package contracts", func() {
|
||||
@@ -47,31 +60,44 @@ var _ = Describe("official typed package contracts", func() {
|
||||
// passed to jobundo. An unknown operation-shaped literal is not evidence
|
||||
// of support; compare independently with the real registered vocabulary.
|
||||
var used []string
|
||||
Expect(filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if d.IsDir() || !strings.HasSuffix(path, ".go") || strings.HasSuffix(path, "_test.go") {
|
||||
return nil
|
||||
}
|
||||
f, err := parser.ParseFile(token.NewFileSet(), path, nil, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ast.Inspect(f, func(n ast.Node) bool {
|
||||
lit, ok := n.(*ast.BasicLit)
|
||||
if !ok || lit.Kind != token.STRING {
|
||||
roots := []string{root}
|
||||
if id == "slack" || id == "telegram" {
|
||||
roots = append(roots, filepath.Join("../../..", connectorRoot))
|
||||
}
|
||||
for _, root := range roots {
|
||||
Expect(filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if d.IsDir() || !strings.HasSuffix(path, ".go") || strings.HasSuffix(path, "_test.go") {
|
||||
return nil
|
||||
}
|
||||
f, err := parser.ParseFile(token.NewFileSet(), path, nil, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ast.Inspect(f, func(n ast.Node) bool {
|
||||
if sel, ok := n.(*ast.SelectorExpr); ok {
|
||||
if pkg, ok := sel.X.(*ast.Ident); ok && pkg.Name == "contract" {
|
||||
if value, ok := connectorConstants[sel.Sel.Name]; ok {
|
||||
used = append(used, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
lit, ok := n.(*ast.BasicLit)
|
||||
if !ok || lit.Kind != token.STRING {
|
||||
return true
|
||||
}
|
||||
value, err := strconv.Unquote(lit.Value)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if slices.Contains(hostops.SupportedOperations(), value) {
|
||||
used = append(used, value)
|
||||
}
|
||||
return true
|
||||
}
|
||||
value, err := strconv.Unquote(lit.Value)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if slices.Contains(hostops.SupportedOperations(), value) {
|
||||
used = append(used, value)
|
||||
}
|
||||
return true
|
||||
})
|
||||
return nil
|
||||
})).To(Succeed())
|
||||
})
|
||||
return nil
|
||||
})).To(Succeed())
|
||||
}
|
||||
declared := append(slices.Clone(want.Required), want.Optional...)
|
||||
slices.Sort(used)
|
||||
used = slices.Compact(used)
|
||||
|
||||
Reference in new issue
Block a user